Browse Source

Merge branch 'upstream'

cl-refactor
subtly 11 years ago
parent
commit
9b4ba633af
  1. 25
      BUILDING.md
  2. 23
      CMakeLists.txt
  3. 2
      CodingStandards.txt
  4. 8
      README.md
  5. 153
      alethzero/Main.ui
  6. 91
      alethzero/MainWin.cpp
  7. 12
      alethzero/MainWin.h
  8. 42
      alethzero/alephzero.pro
  9. 19
      eth/main.cpp
  10. 13
      libethereum/BlockChain.cpp
  11. 13
      libethereum/BlockChain.h
  12. 45
      libethereum/BlockInfo.cpp
  13. 3
      libethereum/BlockInfo.h
  14. 47
      libethereum/Client.cpp
  15. 34
      libethereum/Client.h
  16. 47
      libethereum/Common.cpp
  17. 14
      libethereum/Common.h
  18. 1
      libethereum/FileSystem.cpp
  19. 128
      libethereum/PeerNetwork.cpp
  20. 26
      libethereum/PeerNetwork.h
  21. 3
      libethereum/RLP.h
  22. 131
      libethereum/State.cpp
  23. 40
      libethereum/State.h
  24. 11
      libethereum/Transaction.cpp
  25. 3
      libethereum/Transaction.h
  26. 2
      libethereum/UPnP.cpp
  27. 1
      test/crypto.cpp
  28. 4
      test/peer.cpp
  29. 1
      test/state.cpp

25
BUILDING.md

@ -1,25 +0,0 @@
# Building Ethereum
## Dependencies
secp256k1 implementation: https://github.com/sipa/secp256k1.git
Expects secp256k1 directory to be in same path as cpp-ethereum.
(NOTE: secp256k1 requires a development installation of the GMP library, libssl and libcrypto++.)
libcrypto++, version 5.6.2 or greater (i.e. with SHA3 support). Because it's so recent, it expects this to be built in a directory libcrypto562 in the same path as cpp-ethereum. A recent version of Boost (I use version 1.53) and leveldb (I use version 1.9.0).
A decent C++11 compiler (I use GNU GCC 4.8.1). CMake, version 2.8 or greater.
On Ubuntu:
sudo apt-get install libgmp3-dev libcrypto++-dev libssl-dev libboost-all-dev cmake libleveldb-dev libminiupnpc-dev
## Building
mkdir /path/to/cpp-ethereum/../cpp-ethereum-build
cd /path/to/cpp-ethereum-build
cmake -DCMAKE_BUILD_TYPE=Debug /path/to/cpp-ethereum
make

23
CMakeLists.txt

@ -5,15 +5,32 @@ set(CMAKE_AUTOMOC ON)
cmake_policy(SET CMP0015 NEW)
set(ETH_VERSION 0.1.1)
set(ETH_VERSION 0.1.2)
set(ETH_BUILD_TYPE ${CMAKE_BUILD_TYPE})
set(ETH_BUILD_PLATFORM ${CMAKE_SYSTEM_NAME})
if (CMAKE_COMPILER_IS_MINGW)
set(ETH_BUILD_PLATFORM "${ETH_BUILD_PLATFORM}/mingw")
elseif (CMAKE_COMPILER_IS_MSYS)
set(ETH_BUILD_PLATFORM "${ETH_BUILD_PLATFORM}/msys")
elseif (CMAKE_COMPILER_IS_GNUCXX)
set(ETH_BUILD_PLATFORM "${ETH_BUILD_PLATFORM}/g++")
elseif (CMAKE_COMPILER_IS_MSVC)
set(ETH_BUILD_PLATFORM "${ETH_BUILD_PLATFORM}/msvc")
else ()
set(ETH_BUILD_PLATFORM "${ETH_BUILD_PLATFORM}/unknown")
endif ()
# Initialize CXXFLAGS.
set(CMAKE_CXX_FLAGS "-Wall -std=c++11 -DETH_VERSION=${ETH_VERSION}")
set(CMAKE_CXX_FLAGS "-Wall -std=c++11")
set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g")
set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG")
set(CMAKE_CXX_FLAGS_RELEASE "-O4 -DNDEBUG")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g")
add_definitions("-DETH_VERSION=${ETH_VERSION}")
add_definitions("-DETH_BUILD_TYPE=${ETH_BUILD_TYPE}")
add_definitions("-DETH_BUILD_PLATFORM=${ETH_BUILD_PLATFORM}")
#set(CMAKE_CXX_FLAGS, "${CMAKE_CXX_FLAGS} -DETH_VERSION=${ETH_VERSION} -DETH_BUILD_TYPE=${ETH_BUILD_TYPE} -DETH_BUILD_PLATFORM=${ETH_BUILD_PLATFORM}")
# Compiler-specific C++11 activation.
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
execute_process(

2
CodingStandards.txt

@ -46,7 +46,7 @@ a. File comment is always at top, and includes:
- Original author, date.
- Later maintainers (not contributors - they can be seen through VCS log).
- Copyright.
- Licence (e.g. see COPYING).
- License (e.g. see COPYING).
b. Never use #ifdef/#define/#endif file guards. Prefer #pragma once as first line below file comment.
c. Prefer static const variable to value macros.
d. Prefer inline constexpr functions to function macros.

8
README.md

@ -6,18 +6,16 @@ Gav Wood, 2014.
## Building
See BUILDING.md
See https://github.com/ethereum/cpp-ethereum/wiki/Building and https://github.com/ethereum/cpp-ethereum/wiki/Compatibility-Info-and-Build-Tips .
## Yet To Do
See TODO
## Licence
## License
See LICENCE
See LICENSE
## Contributing
Please read CodingStandards.txt thoroughly before making alterations to the code base. Please do *NOT* use an editor that automatically reformats whitespace away from astylerc or the formating guidelines as describled in CodingStandards.txt.

153
alethzero/Main.ui

@ -91,9 +91,16 @@
<addaction name="mine"/>
<addaction name="create"/>
</widget>
<widget class="QMenu" name="menu_Help">
<property name="title">
<string>&amp;Help</string>
</property>
<addaction name="about"/>
</widget>
<addaction name="menu_File"/>
<addaction name="menu_Network"/>
<addaction name="menu_Tools"/>
<addaction name="menu_Help"/>
</widget>
<widget class="QStatusBar" name="statusbar"/>
<widget class="QDockWidget" name="dockWidget_2">
@ -132,30 +139,47 @@
<number>2</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents_3">
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>4</number>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QSplitter" name="splitter">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<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="QWidget" name="">
<layout class="QGridLayout" name="gridLayout_2">
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Listen on</string>
</property>
</widget>
</item>
<item>
<item row="0" column="1">
<widget class="QSpinBox" name="idealPeers">
<property name="minimum">
<number>1</number>
</property>
<property name="value">
<number>5</number>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Ideal Peers</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="port">
<property name="minimum">
<number>1024</number>
@ -168,7 +192,23 @@
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Client Name</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="clientName">
<property name="placeholderText">
<string>Anonymous</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
@ -207,7 +247,7 @@
<number>10</number>
</property>
<property name="value">
<number>4</number>
<number>1</number>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
@ -270,7 +310,7 @@
</property>
<property name="minimumSize">
<size>
<width>349</width>
<width>408</width>
<height>251</height>
</size>
</property>
@ -291,26 +331,6 @@
<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="5" 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">
@ -318,6 +338,9 @@
</property>
</widget>
</item>
<item row="1" column="3" colspan="2">
<widget class="QComboBox" name="valueUnits"/>
</item>
<item row="1" column="2">
<widget class="QSpinBox" name="value">
<property name="suffix">
@ -331,6 +354,16 @@
</property>
</widget>
</item>
<item row="2" 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>
<item row="0" column="0" colspan="2">
<widget class="QLabel" name="label5">
<property name="sizePolicy">
@ -344,44 +377,45 @@
</property>
</widget>
</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>
<item row="3" column="0" colspan="5">
<widget class="QPlainTextEdit" name="data"/>
</item>
<item row="4" column="4">
<widget class="QPushButton" name="send">
<property name="text">
<string>Send</string>
</property>
</widget>
</item>
<item row="1" column="3" colspan="2">
<widget class="QComboBox" name="valueUnits"/>
</item>
<item row="2" column="0" colspan="2">
<widget class="QLabel" name="label5_3">
<property name="text">
<string>Fee</string>
<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>
<property name="placeholderText">
<string>(Create Contract)</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_2">
<item row="2" column="2" colspan="3">
<widget class="QLabel" name="fee">
<property name="text">
<string>Data</string>
<string/>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="4" column="0" colspan="5">
<widget class="QPlainTextEdit" name="data"/>
<item row="4" column="0" colspan="4">
<widget class="QLabel" name="total">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
@ -459,6 +493,11 @@
<string>&amp;New Address</string>
</property>
</action>
<action name="about">
<property name="text">
<string>&amp;About...</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>

91
alethzero/MainWin.cpp

@ -15,7 +15,8 @@ static void initUnits(QComboBox* _b)
_b->setCurrentIndex(6);
}
#define ETH_QUOTED(A) #A
#define ADD_QUOTES_HELPER(s) #s
#define ADD_QUOTES(s) ADD_QUOTES_HELPER(s)
Main::Main(QWidget *parent) :
QMainWindow(parent),
@ -23,10 +24,8 @@ Main::Main(QWidget *parent) :
{
setWindowFlags(Qt::Window);
ui->setupUi(this);
initUnits(ui->valueUnits);
initUnits(ui->feeUnits);
g_logPost = [=](std::string const& s, char const*) { ui->log->addItem(QString::fromStdString(s)); };
m_client = new Client("AlethZero/v" ETH_QUOTED(ETH_VERSION));
m_client = new Client("AlethZero");
readSettings();
refresh();
@ -42,7 +41,7 @@ Main::Main(QWidget *parent) :
{
m_servers = QString::fromUtf8(_r->readAll()).split("\n", QString::SkipEmptyParts);
});
QNetworkRequest r(QUrl("http://www.ethereum.org/servers.txt"));
QNetworkRequest r(QUrl("http://www.ethereum.org/servers.poc2.txt"));
r.setHeader(QNetworkRequest::UserAgentHeader, "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1712.0 Safari/537.36");
m_webCtrl.get(r);
srand(time(0));
@ -50,6 +49,7 @@ Main::Main(QWidget *parent) :
on_verbosity_sliderMoved();
initUnits(ui->valueUnits);
statusBar()->addPermanentWidget(ui->balance);
statusBar()->addPermanentWidget(ui->peerCount);
statusBar()->addPermanentWidget(ui->blockChain);
@ -62,6 +62,11 @@ Main::~Main()
delete ui;
}
void Main::on_about_triggered()
{
QMessageBox::about(this, "About AlethZero PoC-2", "AlethZero/v" ADD_QUOTES(ETH_VERSION) "/" ADD_QUOTES(ETH_BUILD_TYPE) "/" ADD_QUOTES(ETH_BUILD_PLATFORM) "\nBy Gav Wood, 2014.\nBased on a design by Vitalik Buterin.\n\nTeam Ethereum++ includes: Eric Lombrozo, Marko Simovic, Subtly and several others.");
}
void Main::writeSettings()
{
QSettings s("ethereum", "alethzero");
@ -131,9 +136,8 @@ void Main::refresh()
for (pair<h256, bytes> const& i: m_client->transactionQueue().transactions())
{
Transaction t(i.second);
ui->transactionQueue->addItem(QString("%1 (%2 fee) @ %3 <- %4")
ui->transactionQueue->addItem(QString("%1 @ %2 <- %3")
.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()) );
}
@ -147,9 +151,8 @@ void Main::refresh()
for (auto const& i: RLP(bc.block(h))[1])
{
Transaction t(i.data());
ui->transactions->addItem(QString("%1 (%2) @ %3 <- %4")
ui->transactions->addItem(QString("%1 @ %2 <- %3")
.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()) );
}
@ -168,6 +171,12 @@ void Main::refresh()
m_client->unlock();
}
void Main::on_idealPeers_valueChanged()
{
if (m_client->peerServer())
m_client->peerServer()->setIdealPeerCount(ui->idealPeers->value());
}
void Main::on_ourAccounts_doubleClicked()
{
qApp->clipboard()->setText(ui->ourAccounts->currentItem()->text().section(" @ ", 1));
@ -183,11 +192,62 @@ void Main::on_accounts_doubleClicked()
qApp->clipboard()->setText(ui->accounts->currentItem()->text().section(" @ ", 1));
}
void Main::on_destination_textChanged()
{
updateFee();
}
void Main::on_data_textChanged()
{
m_data = ui->data->toPlainText().split(QRegExp("[^0-9a-fA-Fx]+"), QString::SkipEmptyParts);
updateFee();
}
u256 Main::fee() const
{
return (ui->destination->text().isEmpty() || !ui->destination->text().toInt()) ? m_client->state().fee(m_data.size()) : m_client->state().fee();
}
u256 Main::value() const
{
return ui->value->value() * units()[units().size() - 1 - ui->valueUnits->currentIndex()].first;
}
u256 Main::total() const
{
return value() + fee();
}
void Main::updateFee()
{
ui->fee->setText(QString("(fee: %1)").arg(formatBalance(fee()).c_str()));
auto totalReq = total();
ui->total->setText(QString("Total: %1").arg(formatBalance(totalReq).c_str()));
bool ok = false;
for (auto i: m_myKeys)
if (m_client->state().balance(i.address()) >= totalReq)
{
ok = true;
break;
}
ui->send->setEnabled(ok);
QPalette p = ui->total->palette();
p.setColor(QPalette::WindowText, QColor(ok ? 0x00 : 0x80, 0x00, 0x00));
ui->total->setPalette(p);
}
void Main::on_net_triggered()
{
ui->port->setEnabled(!ui->net->isChecked());
ui->clientName->setEnabled(!ui->net->isChecked());
string n = "AlethZero/v" ADD_QUOTES(ETH_VERSION);
if (ui->clientName->text().size())
n += "/" + ui->clientName->text().toStdString();
n += "/" ADD_QUOTES(ETH_BUILD_TYPE) "/" ADD_QUOTES(ETH_BUILD_PLATFORM);
m_client->setClientVersion(n);
if (ui->net->isChecked())
m_client->startNetwork(ui->port->value(), string(), 0, NodeMode::Full, 5, std::string(), ui->upnp->isChecked());
m_client->startNetwork(ui->port->value(), string(), 0, NodeMode::Full, ui->idealPeers->value(), std::string(), ui->upnp->isChecked());
else
m_client->stopNetwork();
}
@ -227,9 +287,7 @@ void Main::on_mine_triggered()
void Main::on_send_clicked()
{
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;
u256 totalReq = value() + fee();
m_client->lock();
for (auto i: m_myKeys)
if (m_client->state().balance(i.address()) >= totalReq)
@ -237,12 +295,11 @@ void Main::on_send_clicked()
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.reserve(m_data.size());
for (QString const& i: m_data)
data.push_back(u256(i.toStdString()));
m_client->transact(s, r, value, fee, data);
m_client->transact(s, r, value(), data);
refresh();
return;
}

12
alethzero/MainWin.h

@ -32,15 +32,26 @@ private slots:
void on_verbosity_sliderMoved();
void on_ourAccounts_doubleClicked();
void on_accounts_doubleClicked();
void on_destination_textChanged();
void on_data_textChanged();
void on_idealPeers_valueChanged();
void on_value_valueChanged() { updateFee(); }
void on_valueUnits_currentIndexChanged() { updateFee(); }
void on_log_doubleClicked();
void on_about_triggered();
void on_quit_triggered() { close(); }
void refresh();
private:
void updateFee();
void readSettings();
void writeSettings();
eth::u256 fee() const;
eth::u256 total() const;
eth::u256 value() const;
Ui::Main *ui;
eth::Client* m_client;
@ -49,6 +60,7 @@ private:
QTimer* m_refresh;
QStringList m_servers;
QVector<eth::KeyPair> m_myKeys;
QStringList m_data;
QNetworkAccessManager m_webCtrl;
};

42
alethzero/alephzero.pro

@ -1,42 +0,0 @@
#-------------------------------------------------
#
# Project created by QtCreator 2014-01-22T11:47:38
#
#-------------------------------------------------
QT += core gui widgets network
TARGET = alephzero
TEMPLATE = app
CONFIG(debug, debug|release): DEFINES += ETH_DEBUG
QMAKE_CXXFLAGS += -std=c++11
#CONFIG += local_cryptopp
local_cryptopp {
QMAKE_LIBDIR += ../../cryptopp562
CRYPTOPP_LIBS += -lcryptopp
}
!local_cryptopp {
CRYPTOPP_LIBS += -lcryptoppeth
}
INCLUDEPATH += ../../cpp-ethereum
QMAKE_LIBDIR += ../../cpp-ethereum-build/libethereum ../../cpp-ethereum-build/secp256k1
CONFIG(debug, debug|release): LIBS += -Wl,-rpath,../../cpp-ethereum-build/libethereum
LIBS += -lethereum $${CRYPTOPP_LIBS} -lsecp256k1 -lminiupnpc -lleveldb -lgmp -lboost_filesystem -lboost_system
SOURCES += main.cpp \
MainWin.cpp
HEADERS += \
MainWin.h
FORMS += Main.ui

19
eth/main.cpp

@ -20,6 +20,8 @@
* Ethereum client.
*/
#include <thread>
#include <chrono>
#include <fstream>
#include "Defaults.h"
#include "Client.h"
@ -30,6 +32,9 @@
using namespace std;
using namespace eth;
#define ADD_QUOTES_HELPER(s) #s
#define ADD_QUOTES(s) ADD_QUOTES_HELPER(s)
bytes contents(std::string const& _file)
{
std::ifstream is(_file, std::ifstream::binary);
@ -163,7 +168,7 @@ int main(int argc, char** argv)
remoteHost = argv[i];
}
Client c("Ethereum(++)/v0.1", coinbase, dbPath);
Client c("Ethereum(++)/v" ADD_QUOTES(ETH_VERSION) "/" ADD_QUOTES(ETH_BUILD_TYPE) "/" ADD_QUOTES(ETH_BUILD_PLATFORM), coinbase, dbPath);
if (interactive)
{
cout << "Ethereum (++)" << endl;
@ -205,20 +210,18 @@ int main(int argc, char** argv)
string sechex;
string rechex;
u256 amount;
u256 fee;
cin >> sechex >> rechex >> amount >> fee;
cin >> sechex >> rechex >> amount;
Secret secret = h256(fromUserHex(sechex));
Address dest = h160(fromUserHex(rechex));
c.transact(secret, dest, amount, fee);
c.transact(secret, dest, amount);
}
else if (cmd == "send")
{
string rechex;
u256 amount;
u256 fee;
cin >> rechex >> amount >> fee;
cin >> rechex >> amount;
Address dest = h160(fromUserHex(rechex));
c.transact(us.secret(), dest, amount, fee);
c.transact(us.secret(), dest, amount);
}
else if (cmd == "exit")
{
@ -236,7 +239,7 @@ int main(int argc, char** argv)
c.stopMining();
else
c.startMining();
usleep(100000);
this_thread::sleep_for(chrono::milliseconds(100));
}
}

13
libethereum/BlockChain.cpp

@ -124,20 +124,20 @@ void BlockChain::import(bytes const& _block, Overlay const& _db)
auto newHash = eth::sha3(_block);
clog(BlockChainChat) << "Attempting import of " << newHash << "...";
// Check block doesn't already exist first!
if (details(newHash))
{
// cout << " Not new." << endl;
clog(BlockChainChat) << " Not new.";
throw AlreadyHaveBlock();
}
cnote << "Attempting import of " << newHash << "...";
// Work out its number as the parent's number + 1
auto pd = details(bi.parentHash);
if (!pd)
{
cwarn << " Unknown parent " << bi.parentHash;
clog(BlockChainNote) << " Unknown parent " << bi.parentHash;
// We don't know the parent (yet) - discard for now. It'll get resent to us if we find out about its ancestry later on.
throw UnknownParent();
}
@ -177,12 +177,11 @@ void BlockChain::import(bytes const& _block, Overlay const& _db)
{
m_lastBlockHash = newHash;
m_detailsDB->Put(m_writeOptions, ldb::Slice("best"), ldb::Slice((char const*)&newHash, 32));
cnote << " Imported and best.";
clog(BlockChainNote) << " Imported and best.";
}
else
{
cnote << " Imported.";
// cwarn << "Imported block not newest (otd=" << m_details[m_lastBlockHash].totalDifficulty << ", td=" << td << ")";
clog(BlockChainNote) << " Imported but not best (oTD:" << m_details[m_lastBlockHash].totalDifficulty << ", TD:" << td << ")";
}
}

13
libethereum/BlockChain.h

@ -22,6 +22,7 @@
#pragma once
#include "Common.h"
#include "AddressState.h"
namespace ldb = leveldb;
namespace eth
@ -54,6 +55,10 @@ class Overlay;
class AlreadyHaveBlock: public std::exception {};
class UnknownParent: public std::exception {};
struct BlockChainChat: public LogChannel { static const char constexpr* name = "-B-"; static const int verbosity = 7; };
struct BlockChainNote: public LogChannel { static const char constexpr* name = "=B="; static const int verbosity = 1; };
struct BlockChainWarn: public LogChannel { static const char constexpr* name = "!B!"; static const int verbosity = 0; };
/**
* @brief Implements the blockchain database. All data this gives is disk-backed.
*/
@ -91,6 +96,10 @@ public:
h256 genesisHash() const { return m_genesisHash; }
std::vector<std::pair<Address, AddressState>> interestQueue() { std::vector<std::pair<Address, AddressState>> ret; swap(ret, m_interestQueue); return ret; }
void pushInterest(Address _a) { m_interest[_a]++; }
void popInterest(Address _a) { if (m_interest[_a] > 1) m_interest[_a]--; else if (m_interest[_a]) m_interest.erase(_a); }
private:
void checkConsistency();
@ -98,6 +107,10 @@ private:
mutable std::map<h256, BlockDetails> m_details;
mutable std::map<h256, std::string> m_cache;
/// The queue of transactions that have happened that we're interested in.
std::map<Address, int> m_interest;
std::vector<std::pair<Address, AddressState>> m_interestQueue;
ldb::DB* m_db;
ldb::DB* m_detailsDB;

45
libethereum/BlockInfo.cpp

@ -39,6 +39,13 @@ BlockInfo::BlockInfo(bytesConstRef _block)
populate(_block);
}
BlockInfo BlockInfo::fromHeader(bytesConstRef _block)
{
BlockInfo ret;
ret.populateFromHeader(RLP(_block));
return ret;
}
bytes BlockInfo::createGenesisBlock()
{
RLPStream block(3);
@ -79,31 +86,37 @@ void BlockInfo::populateGenesis()
populate(&genesisBlock);
}
void BlockInfo::populate(bytesConstRef _block)
void BlockInfo::populateFromHeader(RLP const& _header)
{
RLP root(_block);
int field = 0;
RLP header = root[0];
if (!header.isList())
throw InvalidBlockFormat(0, header.data());
try
{
hash = eth::sha3(_block);
parentHash = header[field = 0].toHash<h256>();
sha3Uncles = header[field = 1].toHash<h256>();
coinbaseAddress = header[field = 2].toHash<Address>();
stateRoot = header[field = 3].toHash<h256>();
sha3Transactions = header[field = 4].toHash<h256>();
difficulty = header[field = 5].toInt<u256>();
timestamp = header[field = 6].toInt<u256>();
extraData = header[field = 7].toBytes();
nonce = header[field = 8].toHash<h256>();
parentHash = _header[field = 0].toHash<h256>();
sha3Uncles = _header[field = 1].toHash<h256>();
coinbaseAddress = _header[field = 2].toHash<Address>();
stateRoot = _header[field = 3].toHash<h256>();
sha3Transactions = _header[field = 4].toHash<h256>();
difficulty = _header[field = 5].toInt<u256>();
timestamp = _header[field = 6].toInt<u256>();
extraData = _header[field = 7].toBytes();
nonce = _header[field = 8].toHash<h256>();
}
catch (RLP::BadCast)
{
throw InvalidBlockHeaderFormat(field, header[field].data());
throw InvalidBlockHeaderFormat(field, _header[field].data());
}
}
void BlockInfo::populate(bytesConstRef _block)
{
hash = eth::sha3(_block);
RLP root(_block);
RLP header = root[0];
if (!header.isList())
throw InvalidBlockFormat(0, header.data());
populateFromHeader(header);
if (!root[1].isList())
throw InvalidBlockFormat(1, root[1].data());
if (!root[2].isList())

3
libethereum/BlockInfo.h

@ -44,6 +44,8 @@ public:
BlockInfo();
explicit BlockInfo(bytesConstRef _block);
static BlockInfo fromHeader(bytesConstRef _block);
explicit operator bool() const { return timestamp != Invalid256; }
bool operator==(BlockInfo const& _cmp) const
@ -61,6 +63,7 @@ public:
bool operator!=(BlockInfo const& _cmp) const { return !operator==(_cmp); }
static BlockInfo const& genesis() { if (!s_genesis) (s_genesis = new BlockInfo)->populateGenesis(); return *s_genesis; }
void populateFromHeader(RLP const& _header);
void populate(bytesConstRef _block);
void verifyInternals(bytesConstRef _block) const;
void verifyParent(BlockInfo const& _parent) const;

47
libethereum/Client.cpp

@ -21,6 +21,8 @@
#include "Client.h"
#include <chrono>
#include <thread>
#include "Common.h"
#include "Defaults.h"
using namespace std;
@ -30,7 +32,8 @@ Client::Client(std::string const& _clientVersion, Address _us, std::string const
m_clientVersion(_clientVersion),
m_bc(_dbPath),
m_stateDB(State::openDB(_dbPath)),
m_s(_us, m_stateDB)
m_s(_us, m_stateDB),
m_mined(_us, m_stateDB)
{
Defaults::setDBPath(_dbPath);
@ -41,18 +44,18 @@ Client::Client(std::string const& _clientVersion, Address _us, std::string const
m_s.sync(m_tq);
m_changed = true;
static std::string thread_name = "eth";
static const char* c_threadName = "eth";
#if defined(__APPLE__)
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
m_work = dispatch_queue_create(thread_name.c_str(), DISPATCH_QUEUE_SERIAL);
m_work = dispatch_queue_create(c_threadName, DISPATCH_QUEUE_SERIAL);
});
dispatch_async(m_work, ^{
#else
m_work = new thread([&](){
setThreadName(thread_name);
setThreadName(c_threadName);
#endif
while (m_workState != Deleting) work(); m_workState = Deleted;
@ -64,7 +67,7 @@ Client::~Client()
if (m_workState == Active)
m_workState = Deleting;
while (m_workState != Deleted)
usleep(10000);
this_thread::sleep_for(chrono::milliseconds(10));
}
void Client::startNetwork(short _listenPort, std::string const& _seedHost, short _port, NodeMode _mode, unsigned _peers, string const& _publicIP, bool _upnp)
@ -93,6 +96,7 @@ void Client::stopNetwork()
void Client::startMining()
{
m_doMine = true;
m_miningStarted = true;
}
void Client::stopMining()
@ -100,14 +104,13 @@ void Client::stopMining()
m_doMine = false;
}
void Client::transact(Secret _secret, Address _dest, u256 _amount, u256 _fee, u256s _data)
void Client::transact(Secret _secret, Address _dest, u256 _amount, u256s _data)
{
m_lock.lock();
Transaction t;
t.nonce = m_s.transactionsFrom(toAddress(_secret));
t.receiveAddress = _dest;
t.value = _amount;
t.fee = _fee;
t.data = _data;
t.sign(_secret);
m_tq.attemptImport(t.rlp());
@ -118,12 +121,14 @@ void Client::transact(Secret _secret, Address _dest, u256 _amount, u256 _fee, u2
void Client::work()
{
m_lock.lock();
bool changed = false;
// Process network events.
// Synchronise block chain with network.
// Will broadcast any of our (new) transactions and blocks, and collect & add any of their (new) transactions and blocks.
if (m_net)
if (m_net->process(m_bc, m_tq, m_stateDB))
m_changed = true;
changed = true;
// Synchronise state to block chain.
// This should remove any transactions on our queue that are included within our state.
@ -133,16 +138,25 @@ void Client::work()
// all blocks.
// Resynchronise state with block chain & trans
if (m_s.sync(m_bc))
m_changed = true;
if (m_s.sync(m_tq))
m_changed = true;
{
changed = true;
m_mined = m_s;
}
m_lock.unlock();
if (m_doMine)
{
if (m_miningStarted)
{
m_mined = m_s;
m_mined.sync(m_tq);
m_mined.commitToMine(m_bc);
}
m_miningStarted = false;
// Mine for a while.
m_s.commitToMine(m_bc);
MineInfo mineInfo = m_s.mine(100);
MineInfo mineInfo = m_mined.mine(100);
m_mineProgress.best = max(m_mineProgress.best, mineInfo.best);
m_mineProgress.current = mineInfo.best;
m_mineProgress.requirement = mineInfo.requirement;
@ -151,14 +165,17 @@ void Client::work()
{
// Import block.
m_lock.lock();
m_bc.attemptImport(m_s.blockData(), m_stateDB);
m_bc.attemptImport(m_mined.blockData(), m_stateDB);
m_mineProgress.best = 0;
m_lock.unlock();
m_changed = true;
m_miningStarted = true; // need to re-commit to mine.
}
}
else
usleep(100000);
this_thread::sleep_for(chrono::milliseconds(100));
m_changed = m_changed || changed;
}
void Client::lock()

34
libethereum/Client.h

@ -40,6 +40,18 @@ struct MineProgress
uint current;
};
class Client;
class ClientGuard
{
public:
inline ClientGuard(Client* _c);
inline ~ClientGuard();
private:
Client* m_client;
};
class Client
{
public:
@ -50,16 +62,16 @@ public:
~Client();
/// Executes the given transaction.
void transact(Secret _secret, Address _dest, u256 _amount, u256 _fee, u256s _data = u256s());
void transact(Secret _secret, Address _dest, u256 _amount, u256s _data = u256s());
/// Requires transactions involving this address be queued for inspection.
void setInterest(Address _dest);
/// @returns incoming minable transactions that we wanted to be notified of. Clears the queue.
Transactions pendingQueue();
Transactions pendingQueue() { ClientGuard g(this); return m_tq.interestQueue(); }
/// @returns alterations in state of a mined block that we wanted to be notified of. Clears the queue.
std::vector<std::pair<Address, AddressState>> minedQueue();
std::vector<std::pair<Address, AddressState>> minedQueue() { ClientGuard g(this); return m_bc.interestQueue(); }
// Not yet - probably best as using some sort of signals implementation.
/// Calls @a _f when a valid transaction is received that involves @a _dest and once per such transaction.
@ -84,6 +96,8 @@ public:
/// Get the object representing the transaction queue.
TransactionQueue const& transactionQueue() const { return m_tq; }
void setClientVersion(std::string const& _name) { m_clientVersion = _name; }
// Network stuff:
/// Get information on the current peer set.
@ -97,6 +111,8 @@ public:
void connect(std::string const& _seedHost, short _port = 30303);
/// Stop the network subsystem.
void stopNetwork();
/// Get access to the peer server object. This will be null if the network isn't online.
PeerServer* peerServer() const { return m_net; }
// Mining stuff:
@ -119,6 +135,7 @@ private:
TransactionQueue m_tq; ///< Maintains list of incoming transactions not yet on the block chain.
Overlay m_stateDB; ///< Acts as the central point for the state database, so multiple States can share it.
State m_s; ///< The present state of the client.
State m_mined; ///< The state of the client which we're mining (i.e. it'll have all the rewards added).
PeerServer* m_net = nullptr; ///< Should run in background and send us events when blocks found and allow us to send blocks as required.
#if defined(__APPLE__)
@ -131,8 +148,19 @@ private:
enum { Active = 0, Deleting, Deleted } m_workState = Active;
bool m_doMine = false; ///< Are we supposed to be mining?
MineProgress m_mineProgress;
mutable bool m_miningStarted = false;
mutable bool m_changed;
};
inline ClientGuard::ClientGuard(Client* _c): m_client(_c)
{
m_client->lock();
}
inline ClientGuard::~ClientGuard()
{
m_client->unlock();
}
}

47
libethereum/Common.cpp

@ -43,8 +43,8 @@ int eth::g_logVerbosity = 8;
map<type_info const*, bool> eth::g_logOverride;
#if !defined(__APPLE__)
thread_local std::string eth::t_logThreadName = "???";
static std::string g_mainThreadName = (eth::t_logThreadName = "main");
thread_local char const* eth::t_logThreadName = "???";
static char const* g_mainThreadName = (eth::t_logThreadName = "main");
#endif
void eth::simpleDebugOut(std::string const& _s, char const*)
@ -190,14 +190,51 @@ Address eth::toAddress(Secret _private)
KeyPair KeyPair::create()
{
secp256k1_start();
static std::mt19937_64 s_eng(time(0));
std::uniform_int_distribution<byte> d(0, 255);
KeyPair ret;
for (int i = 0; i < 100; ++i)
{
h256 sec;
for (uint i = 0; i < 32; ++i)
ret.m_secret[i] = d(s_eng);
ret.m_address = toAddress(ret.m_secret);
sec[i] = d(s_eng);
KeyPair ret(sec);
if (ret.address())
return ret;
}
return KeyPair();
}
KeyPair::KeyPair(h256 _sec):
m_secret(_sec)
{
int ok = secp256k1_ecdsa_seckey_verify(m_secret.data());
if (!ok)
return;
byte pubkey[65];
int pubkeylen = 65;
ok = secp256k1_ecdsa_pubkey_create(pubkey, &pubkeylen, m_secret.data(), 0);
if (!ok || pubkeylen != 65)
return;
ok = secp256k1_ecdsa_pubkey_verify(pubkey, 65);
if (!ok)
return;
m_secret = m_secret;
memcpy(m_public.data(), &(pubkey[1]), 64);
m_address = right160(eth::sha3(bytesConstRef(&(pubkey[1]), 64)));
#if ETH_ADDRESS_DEBUG
cout << "---- ADDRESS -------------------------------" << endl;
cout << "SEC: " << m_secret << endl;
cout << "PUB: " << m_public << endl;
cout << "ADR: " << m_address << endl;
#endif
}
static const vector<pair<u256, string>> g_units =
{

14
libethereum/Common.h

@ -127,6 +127,7 @@ inline std::ostream& operator<<(std::ostream& _out, FixedHash<N> const& _h)
return _out;
}
using h512 = FixedHash<64>;
using h256 = FixedHash<32>;
using h160 = FixedHash<20>;
using h256s = std::vector<h256>;
@ -135,6 +136,7 @@ using h256Set = std::set<h256>;
using h160Set = std::set<h160>;
using Secret = h256;
using Public = h512;
using Address = h160;
using Addresses = h160s;
@ -158,8 +160,8 @@ public:
extern std::map<std::type_info const*, bool> g_logOverride;
#if !defined(__APPLE__)
extern thread_local std::string t_logThreadName;
inline void setThreadName(std::string const& _n) { t_logThreadName = _n; }
extern thread_local char const* t_logThreadName;
inline void setThreadName(char const* _n) { t_logThreadName = _n; }
#endif
struct LogChannel { static const char constexpr* name = " "; static const int verbosity = 1; };
@ -167,7 +169,7 @@ 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; };
struct DebugChannel: public LogChannel { static const char constexpr* name = "---"; static const int verbosity = 7; };
extern int g_logVerbosity;
extern std::function<void(std::string const&, char const*)> g_logPost;
@ -434,15 +436,19 @@ class KeyPair
{
public:
KeyPair() {}
KeyPair(Secret _k): m_secret(_k), m_address(toAddress(_k)) {}
KeyPair(Secret _k);
static KeyPair create();
Secret const& secret() const { return m_secret; }
Secret const& sec() const { return m_secret; }
Public const& pub() const { return m_public; }
Address const& address() const { return m_address; }
private:
Secret m_secret;
Public m_public;
Address m_address;
};

1
libethereum/FileSystem.cpp

@ -22,6 +22,7 @@
*/
#include "FileSystem.h"
#include "Common.h"
#ifdef _WIN32
#include <shlobj.h>

128
libethereum/PeerNetwork.cpp

@ -30,6 +30,7 @@
#endif
#include <chrono>
#include <thread>
#include "Exceptions.h"
#include "Common.h"
#include "BlockChain.h"
@ -42,6 +43,8 @@ using namespace eth;
#define clogS(X) eth::LogOutputStream<X, true>(false) << "| " << std::setw(2) << m_socket.native_handle() << "] "
static const int c_protocolVersion = 3;
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).
@ -94,21 +97,29 @@ bool PeerSession::interpret(RLP const& _r)
m_protocolVersion = _r[1].toInt<uint>();
m_networkId = _r[2].toInt<uint>();
auto clientVersion = _r[3].toString();
m_caps = _r.itemCount() > 4 ? _r[4].toInt<uint>() : 0x07;
m_listenPort = _r.itemCount() > 5 ? _r[5].toInt<short>() : 0;
m_caps = _r[4].toInt<uint>();
m_listenPort = _r[5].toInt<short>();
m_id = _r[6].toHash<h512>();
clogS(NetMessageSummary) << "Hello: " << clientVersion << "V[" << m_protocolVersion << "/" << m_networkId << "]" << asHex(m_id.ref().cropped(0, 4)) << showbase << hex << m_caps << dec << m_listenPort;
clogS(NetMessageSummary) << "Hello: " << clientVersion << "V[" << m_protocolVersion << "/" << m_networkId << "]" << showbase << hex << m_caps << dec << m_listenPort;
if (m_server->m_peers.count(m_id) || !m_id)
{
// Already connected.
disconnect(DuplicatePeer);
}
m_server->m_peers[m_id] = shared_from_this();
if (m_protocolVersion != 1 || m_networkId != m_reqNetworkId)
if (m_protocolVersion != c_protocolVersion || m_networkId != m_reqNetworkId)
{
disconnect();
disconnect(IncompatibleProtocol);
return false;
}
try
{ m_info = PeerInfo({clientVersion, m_socket.remote_endpoint().address().to_string(), (short)m_socket.remote_endpoint().port(), std::chrono::steady_clock::duration()}); }
catch (...)
{
disconnect();
disconnect(BadProtocol);
return false;
}
@ -131,13 +142,30 @@ bool PeerSession::interpret(RLP const& _r)
break;
}
case DisconnectPacket:
clogS(NetMessageSummary) << "Disconnect";
{
string reason = "Unspecified";
if (_r.itemCount() > 1 && _r[1].isInt())
switch (_r[1].toInt<int>())
{
case DisconnectRequested: reason = "Disconnect was requested."; break;
case TCPError: reason = "Low-level TCP communication error."; break;
case BadProtocol: reason = "Data format error."; break;
case UselessPeer: reason = "We had no use to peer."; break;
case TooManyPeers: reason = "Peer had too many connections."; break;
case DuplicatePeer: reason = "Peer was already connected."; break;
case WrongGenesis: reason = "Disagreement over genesis block."; break;
case IncompatibleProtocol: reason = "Peer protocol versions are incompatible."; break;
case ClientQuit: reason = "Peer is exiting."; break;
}
clogS(NetMessageSummary) << "Disconnect (reason: " << reason << ")";
if (m_socket.is_open())
clogS(NetNote) << "Closing " << m_socket.remote_endpoint();
else
clogS(NetNote) << "Remote closed.";
m_socket.close();
return false;
}
case PingPacket:
{
// clogS(NetMessageSummary) << "Ping";
@ -152,14 +180,14 @@ bool PeerSession::interpret(RLP const& _r)
case GetPeersPacket:
{
clogS(NetMessageSummary) << "GetPeers";
std::vector<bi::tcp::endpoint> peers = m_server->potentialPeers();
auto peers = m_server->potentialPeers();
RLPStream s;
prep(s).appendList(peers.size() + 1);
s << PeersPacket;
for (auto i: peers)
{
clogS(NetMessageDetail) << "Sending peer " << i;
s.appendList(2) << i.address().to_v4().to_bytes() << i.port();
clogS(NetMessageDetail) << "Sending peer " << asHex(i.first.ref().cropped(0, 4)) << i.second;
s.appendList(3) << i.second.address().to_v4().to_bytes() << i.second.port() << i.first;
}
sealAndSend(s);
break;
@ -169,7 +197,16 @@ bool PeerSession::interpret(RLP const& _r)
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>());
clogS(NetAllDetail) << "Checking: " << ep;
Public id;
if (_r[i].itemCount() > 2)
id = _r[i][2].toHash<Public>();
clogS(NetAllDetail) << "Checking: " << ep << "(" << asHex(id.ref().cropped(0, 4)) << ")";
// check that it's not us or one we already know:
if (id && (m_server->m_key.pub() == id || m_server->m_peers.count(id) || m_server->m_incomingPeers.count(id)))
goto CONTINUE;
// check that we're not already connected to addr:
if (!ep.port())
goto CONTINUE;
@ -177,16 +214,16 @@ bool PeerSession::interpret(RLP const& _r)
if (ep.address() == i && ep.port() == m_server->listenPort())
goto CONTINUE;
for (auto i: m_server->m_peers)
if (shared_ptr<PeerSession> p = i.lock())
if (shared_ptr<PeerSession> p = i.second.lock())
{
clogS(NetAllDetail) << " ...against " << p->endpoint();
if (p->m_socket.is_open() && p->endpoint() == ep)
goto CONTINUE;
}
for (auto i: m_server->m_incomingPeers)
if (i == ep)
if (i.second == ep)
goto CONTINUE;
m_server->m_incomingPeers.push_back(ep);
m_server->m_incomingPeers.insert(make_pair(id, ep));
clogS(NetMessageDetail) << "New peer: " << ep;
CONTINUE:;
}
@ -313,7 +350,7 @@ bool PeerSession::interpret(RLP const& _r)
if (noGood == m_server->m_chain->genesisHash())
{
clogS(NetWarn) << "Discordance over genesis block! Disconnect.";
disconnect();
disconnect(WrongGenesis);
}
else
{
@ -410,14 +447,14 @@ void PeerSession::dropped()
}catch (...){}
m_socket.close();
for (auto i = m_server->m_peers.begin(); i != m_server->m_peers.end(); ++i)
if (i->lock().get() == this)
if (i->second.lock().get() == this)
{
m_server->m_peers.erase(i);
break;
}
}
void PeerSession::disconnect()
void PeerSession::disconnect(int _reason)
{
if (m_socket.is_open())
{
@ -425,7 +462,7 @@ void PeerSession::disconnect()
{
RLPStream s;
prep(s);
s.appendList(1) << DisconnectPacket;
s.appendList(1) << DisconnectPacket << _reason;
sealAndSend(s);
m_disconnect = chrono::steady_clock::now();
}
@ -446,9 +483,7 @@ void PeerSession::start()
{
RLPStream s;
prep(s);
s.appendList(m_server->m_public.port() ? 6 : 5) << HelloPacket << (uint)1 << (uint)m_server->m_requiredNetworkId << m_server->m_clientVersion << (m_server->m_mode == NodeMode::Full ? 0x07 : m_server->m_mode == NodeMode::PeerServer ? 0x01 : 0);
if (m_server->m_public.port())
s << m_server->m_public.port();
s.appendList(m_server->m_public.port() ? 6 : 5) << HelloPacket << (uint)c_protocolVersion << (uint)m_server->m_requiredNetworkId << m_server->m_clientVersion << (m_server->m_mode == NodeMode::Full ? 0x07 : m_server->m_mode == NodeMode::PeerServer ? 0x01 : 0) << m_server->m_public.port() << m_server->m_key.pub();
sealAndSend(s);
ping();
@ -516,31 +551,34 @@ PeerServer::PeerServer(std::string const& _clientVersion, BlockChain const& _ch,
m_chain(&_ch),
m_acceptor(m_ioService, bi::tcp::endpoint(bi::tcp::v4(), _port)),
m_socket(m_ioService),
m_key(KeyPair::create()),
m_requiredNetworkId(_networkId)
{
populateAddresses();
determinePublic(_publicAddress, _upnp);
ensureAccepting();
clog(NetNote) << "Mode: " << (_m == NodeMode::PeerServer ? "PeerServer" : "Full");
clog(NetNote) << "Id:" << asHex(m_key.address().ref().cropped(0, 4)) << "Mode: " << (_m == NodeMode::PeerServer ? "PeerServer" : "Full");
}
PeerServer::PeerServer(std::string const& _clientVersion, uint _networkId):
PeerServer::PeerServer(std::string const& _clientVersion, uint _networkId, NodeMode _m):
m_clientVersion(_clientVersion),
m_mode(_m),
m_listenPort(-1),
m_acceptor(m_ioService, bi::tcp::endpoint(bi::tcp::v4(), 0)),
m_socket(m_ioService),
m_key(KeyPair::create()),
m_requiredNetworkId(_networkId)
{
// populate addresses.
populateAddresses();
clog(NetNote) << "Genesis: " << m_chain->genesisHash();
clog(NetNote) << "Id:" << asHex(m_key.address().ref().cropped(0, 4)) << "Mode: " << (m_mode == NodeMode::PeerServer ? "PeerServer" : "Full");
}
PeerServer::~PeerServer()
{
for (auto const& i: m_peers)
if (auto p = i.lock())
p->disconnect();
if (auto p = i.second.lock())
p->disconnect(ClientQuit);
delete m_upnp;
}
@ -654,17 +692,17 @@ void PeerServer::populateAddresses()
#endif
}
std::vector<bi::tcp::endpoint> PeerServer::potentialPeers()
std::map<Public, bi::tcp::endpoint> PeerServer::potentialPeers()
{
std::vector<bi::tcp::endpoint> ret;
std::map<Public, bi::tcp::endpoint> ret;
if (!m_public.address().is_unspecified())
ret.push_back(m_public);
ret.insert(make_pair(m_key.pub(), m_public));
for (auto i: m_peers)
if (auto j = i.lock())
if (auto j = i.second.lock())
{
auto ep = j->endpoint();
if (ep.port())
ret.push_back(ep);
if (ep.port() && j->m_id)
ret.insert(make_pair(i.first, ep));
}
return ret;
}
@ -684,7 +722,6 @@ void PeerServer::ensureAccepting()
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)
@ -712,7 +749,6 @@ void PeerServer::connect(bi::tcp::endpoint const& _ep)
else
{
auto p = make_shared<PeerSession>(this, std::move(*s), m_requiredNetworkId);
m_peers.push_back(p);
clog(NetNote) << "Connected to " << p->endpoint();
p->start();
}
@ -733,7 +769,7 @@ bool PeerServer::process(BlockChain& _bc)
if (fullProcess)
for (auto i = m_peers.begin(); i != m_peers.end();)
{
auto p = i->lock();
auto p = i->second.lock();
if (p && p->m_socket.is_open() &&
(p->m_disconnect == chrono::steady_clock::time_point::max() || chrono::steady_clock::now() - p->m_disconnect < chrono::seconds(1))) // kill old peers that should be disconnected.
++i;
@ -782,7 +818,7 @@ bool PeerServer::process(BlockChain& _bc, TransactionQueue& _tq, Overlay& _o)
if (fullProcess)
{
for (auto j: m_peers)
if (auto p = j.lock())
if (auto p = j.second.lock())
{
bytes b;
uint n = 0;
@ -798,7 +834,7 @@ bool PeerServer::process(BlockChain& _bc, TransactionQueue& _tq, Overlay& _o)
RLPStream ts;
PeerSession::prep(ts);
ts.appendList(n + 1) << TransactionsPacket;
ts.appendRaw(b).swapOut(b);
ts.appendRaw(b, n).swapOut(b);
seal(b);
p->send(&b);
}
@ -818,7 +854,7 @@ bool PeerServer::process(BlockChain& _bc, TransactionQueue& _tq, Overlay& _o)
ts.appendRaw(_bc.block(_bc.currentHash())).swapOut(b);
seal(b);
for (auto j: m_peers)
if (auto p = j.lock())
if (auto p = j.second.lock())
{
if (!p->m_knownBlocks.count(_bc.currentHash()))
p->send(&b);
@ -867,7 +903,7 @@ bool PeerServer::process(BlockChain& _bc, TransactionQueue& _tq, Overlay& _o)
(PeerSession::prep(s).appendList(1) << GetPeersPacket).swapOut(b);
seal(b);
for (auto const& i: m_peers)
if (auto p = i.lock())
if (auto p = i.second.lock())
if (p->isOpen())
p->send(&b);
m_lastPeersRequest = chrono::steady_clock::now();
@ -879,8 +915,8 @@ bool PeerServer::process(BlockChain& _bc, TransactionQueue& _tq, Overlay& _o)
break;
}
connect(m_incomingPeers.back());
m_incomingPeers.pop_back();
connect(m_incomingPeers.begin()->second);
m_incomingPeers.erase(m_incomingPeers.begin());
}
}
}
@ -900,7 +936,7 @@ bool PeerServer::process(BlockChain& _bc, TransactionQueue& _tq, Overlay& _o)
shared_ptr<PeerSession> worst;
unsigned agedPeers = 0;
for (auto i: m_peers)
if (auto p = i.lock())
if (auto p = i.second.lock())
if ((m_mode != NodeMode::PeerServer || p->m_caps != 0x01) && chrono::steady_clock::now() > p->m_connect + chrono::milliseconds(old)) // don't throw off new peers; peer-servers should never kick off other peer-servers.
{
++agedPeers;
@ -909,7 +945,7 @@ bool PeerServer::process(BlockChain& _bc, TransactionQueue& _tq, Overlay& _o)
}
if (!worst || agedPeers <= m_idealPeerCount)
break;
worst->disconnect();
worst->disconnect(TooManyPeers);
}
}
@ -919,10 +955,10 @@ bool PeerServer::process(BlockChain& _bc, TransactionQueue& _tq, Overlay& _o)
std::vector<PeerInfo> PeerServer::peers() const
{
const_cast<PeerServer*>(this)->pingAll();
usleep(200000);
this_thread::sleep_for(chrono::milliseconds(200));
std::vector<PeerInfo> ret;
for (auto& i: m_peers)
if (auto j = i.lock())
if (auto j = i.second.lock())
if (j->m_socket.is_open())
ret.push_back(j->m_info);
return ret;
@ -931,6 +967,6 @@ std::vector<PeerInfo> PeerServer::peers() const
void PeerServer::pingAll()
{
for (auto& i: m_peers)
if (auto j = i.lock())
if (auto j = i.second.lock())
j->ping();
}

26
libethereum/PeerNetwork.h

@ -21,6 +21,7 @@
#pragma once
#include <map>
#include <memory>
#include <utility>
#include <boost/asio.hpp>
@ -60,6 +61,19 @@ enum PacketType
GetTransactionsPacket
};
enum DisconnectReason
{
DisconnectRequested = 0,
TCPError,
BadProtocol,
UselessPeer,
TooManyPeers,
DuplicatePeer,
WrongGenesis,
IncompatibleProtocol,
ClientQuit
};
class PeerServer;
struct PeerInfo
@ -79,7 +93,7 @@ public:
~PeerSession();
void start();
void disconnect();
void disconnect(int _reason);
void ping();
@ -102,6 +116,7 @@ private:
bi::tcp::socket m_socket;
std::array<byte, 65536> m_data;
PeerInfo m_info;
Public m_id;
bytes m_incoming;
uint m_protocolVersion;
@ -137,7 +152,7 @@ public:
/// Start server, listening for connections on the given port.
PeerServer(std::string const& _clientVersion, BlockChain const& _ch, uint _networkId, short _port, NodeMode _m = NodeMode::Full, std::string const& _publicAddress = std::string(), bool _upnp = true);
/// Start server, but don't listen.
PeerServer(std::string const& _clientVersion, uint _networkId);
PeerServer(std::string const& _clientVersion, uint _networkId, NodeMode _m = NodeMode::Full);
~PeerServer();
/// Connect to a peer explicitly.
@ -172,7 +187,7 @@ private:
void populateAddresses();
void determinePublic(std::string const& _publicAddress, bool _upnp);
void ensureAccepting();
std::vector<bi::tcp::endpoint> potentialPeers();
std::map<Public, bi::tcp::endpoint> potentialPeers();
std::string m_clientVersion;
NodeMode m_mode = NodeMode::Full;
@ -186,13 +201,14 @@ private:
UPnP* m_upnp = nullptr;
bi::tcp::endpoint m_public;
KeyPair m_key;
uint m_requiredNetworkId;
std::vector<std::weak_ptr<PeerSession>> m_peers;
std::map<Public, std::weak_ptr<PeerSession>> m_peers;
std::vector<bytes> m_incomingTransactions;
std::vector<bytes> m_incomingBlocks;
std::vector<bi::tcp::endpoint> m_incomingPeers;
std::multimap<Public, bi::tcp::endpoint> m_incomingPeers;
h256 m_latestBlockSent;
std::set<h256> m_transactionsSent;

3
libethereum/RLP.h

@ -278,8 +278,7 @@ public:
RLPStream& append(bytes const& _s) { return append(bytesConstRef(&_s)); }
RLPStream& append(std::string const& _s) { return append(bytesConstRef(_s)); }
RLPStream& append(char const* _s) { return append(std::string(_s)); }
RLPStream& append(h160 _s, bool _compact = false) { return append(_s.ref(), _compact); }
RLPStream& append(h256 _s, bool _compact = false) { return append(_s.ref(), _compact); }
template <unsigned N> RLPStream& append(FixedHash<N> _s, bool _compact = false) { return append(_s.ref(), _compact); }
/// Appends an arbitrary RLP fragment - this *must* be a single item.
RLPStream& append(RLP const& _rlp, uint _itemCount = 1) { return appendRaw(_rlp.data(), _itemCount); }

131
libethereum/State.cpp

@ -46,20 +46,15 @@
using namespace std;
using namespace eth;
u256 const State::c_stepFee = 10000;
u256 const State::c_dataFee = 20000;
u256 const State::c_memoryFee = 30000;
u256 const State::c_extroFee = 40000;
u256 const State::c_cryptoFee = 50000;
u256 const State::c_newContractFee = 60000;
u256 const State::c_txFee = 0;
u256 const State::c_blockReward = 1000000000000;
#if NDEBUG
u256 const eth::c_genesisDifficulty = (u256)1 << 22;
#else
u256 const c_stepFee = 1;
u256 const c_dataFee = 20;
u256 const c_memoryFee = 5;
u256 const c_extroFee = 40;
u256 const c_cryptoFee = 20;
u256 const c_newContractFee = 100;
u256 const c_txFee = 100;
u256 const eth::c_genesisDifficulty = (u256)1 << 22;
#endif
std::map<Address, AddressState> const& eth::genesisState()
{
@ -90,8 +85,14 @@ Overlay State::openDB(std::string _path, bool _killExisting)
return Overlay(db);
}
State::State(Address _coinbaseAddress, Overlay const& _db): m_db(_db), m_state(&m_db), m_ourAddress(_coinbaseAddress)
State::State(Address _coinbaseAddress, Overlay const& _db):
m_db(_db),
m_state(&m_db),
m_ourAddress(_coinbaseAddress)
{
m_blockReward = u256(15000000000) * 100000000;
m_fees.setMultiplier(u256(100000) * 1000000000);
secp256k1_start();
// Initialise to the state entailed by the genesis block; this guarantees the trie is built correctly.
@ -106,6 +107,46 @@ State::State(Address _coinbaseAddress, Overlay const& _db): m_db(_db), m_state(&
assert(m_state.root() == m_previousBlock.stateRoot);
}
State::State(State const& _s):
m_db(_s.m_db),
m_state(&m_db, _s.m_state.root()),
m_transactions(_s.m_transactions),
m_cache(_s.m_cache),
m_previousBlock(_s.m_previousBlock),
m_currentBlock(_s.m_currentBlock),
m_currentNumber(_s.m_currentNumber),
m_ourAddress(_s.m_ourAddress),
m_fees(_s.m_fees),
m_blockReward(_s.m_blockReward)
{
}
State& State::operator=(State const& _s)
{
m_db = _s.m_db;
m_state.open(&m_db, _s.m_state.root());
m_transactions = _s.m_transactions;
m_cache = _s.m_cache;
m_previousBlock = _s.m_previousBlock;
m_currentBlock = _s.m_currentBlock;
m_currentNumber = _s.m_currentNumber;
m_ourAddress = _s.m_ourAddress;
m_fees = _s.m_fees;
m_blockReward = _s.m_blockReward;
return *this;
}
void FeeStructure::setMultiplier(u256 _x)
{
m_stepFee = c_stepFee * _x;
m_dataFee = c_dataFee * _x;
m_memoryFee = c_memoryFee * _x;
m_extroFee = c_extroFee * _x;
m_cryptoFee = c_cryptoFee * _x;
m_newContractFee = c_newContractFee * _x;
m_txFee = c_txFee * _x;
}
void State::ensureCached(Address _a, bool _requireMemory, bool _forceCreate) const
{
auto it = m_cache.find(_a);
@ -303,7 +344,7 @@ u256 State::playback(bytesConstRef _block, BlockInfo const& _grandParent, bool _
Addresses rewarded;
for (auto const& i: RLP(_block)[2])
{
BlockInfo uncle(i.data());
BlockInfo uncle = BlockInfo::fromHeader(i.data());
if (m_previousBlock.parentHash != uncle.parentHash)
throw InvalidUncle();
if (_grandParent)
@ -350,6 +391,8 @@ u256 State::playback(bytesConstRef _block, BlockInfo const& _grandParent, bool _
// (i.e. all the transactions we executed).
void State::commitToMine(BlockChain const& _bc)
{
cnote << "Commiting to mine on" << m_previousBlock.hash;
if (m_currentBlock.sha3Transactions != h256() || m_currentBlock.sha3Uncles != h256())
return;
@ -417,7 +460,7 @@ MineInfo State::mine(uint _msTimeout)
ret.appendRaw(m_currentUncles);
ret.swapOut(m_currentBytes);
m_currentBlock.hash = sha3(m_currentBytes);
cout << "*** SUCCESS: Mined " << m_currentBlock.hash << " (parent: " << m_currentBlock.parentHash << ")" << endl;
cnote << "Mined " << m_currentBlock.hash << "(parent: " << m_currentBlock.parentHash << ")";
}
else
m_currentBytes.clear();
@ -525,11 +568,11 @@ void State::execute(bytesConstRef _rlp)
void State::applyRewards(Addresses const& _uncleAddresses)
{
u256 r = c_blockReward;
u256 r = m_blockReward;
for (auto const& i: _uncleAddresses)
{
addBalance(i, c_blockReward * 4 / 3);
r += c_blockReward / 8;
addBalance(i, m_blockReward * 4 / 3);
r += m_blockReward / 8;
}
addBalance(m_currentBlock.coinbaseAddress, r);
}
@ -544,31 +587,32 @@ void State::executeBare(Transaction const& _t, Address _sender)
throw InvalidNonce(nonceReq, _t.nonce);
// Not considered invalid - just pointless.
if (balance(_sender) < _t.value + _t.fee)
u256 fee = _t.receiveAddress ? m_fees.m_txFee : (_t.data.size() * m_fees.m_memoryFee + m_fees.m_newContractFee);
if (balance(_sender) < _t.value + fee)
throw NotEnoughCash();
// TODO: check fee is sufficient?
// Increment associated nonce for sender.
noteSending(_sender);
if (_t.receiveAddress)
{
subBalance(_sender, _t.value + _t.fee);
subBalance(_sender, _t.value + fee);
addBalance(_t.receiveAddress, _t.value);
addBalance(m_currentBlock.coinbaseAddress, _t.fee);
if (isContractAddress(_t.receiveAddress))
{
MinerFeeAdder feeAdder({this, 0}); // will add fee on destruction.
execute(_t.receiveAddress, _sender, _t.value, _t.fee, _t.data, &feeAdder.fee);
execute(_t.receiveAddress, _sender, _t.value, _t.data, &feeAdder.fee);
}
}
else
{
// Try to make a new contract
if (_t.fee < _t.data.size() * c_memoryFee + c_newContractFee)
throw FeeTooSmall();
#if ETH_SENDER_PAYS_SETUP
if (balance(_sender) < _t.value + fee)
#else
if (_t.value < fee)
#endif
throw NotEnoughCash();
Address newAddress = low160(_t.sha3());
@ -584,9 +628,13 @@ void State::executeBare(Transaction const& _t, Address _sender)
else
mem.at(i) = _t.data[i];
subBalance(_sender, _t.value + _t.fee);
#if ETH_SENDER_PAYS_SETUP
subBalance(_sender, _t.value + fee);
addBalance(newAddress, _t.value);
addBalance(m_currentBlock.coinbaseAddress, _t.fee);
#else
subBalance(_sender, _t.value);
addBalance(newAddress, _t.value - fee);
#endif
}
}
@ -598,7 +646,7 @@ inline Address asAddress(u256 _item)
return left160(h256(_item));
}
void State::execute(Address _myAddress, Address _txSender, u256 _txValue, u256 _txFee, u256s const& _txData, u256* _totalFee)
void State::execute(Address _myAddress, Address _txSender, u256 _txValue, u256s const& _txData, u256* _totalFee)
{
std::vector<u256> stack;
@ -637,7 +685,7 @@ void State::execute(Address _myAddress, Address _txSender, u256 _txValue, u256 _
{
stepCount++;
bigint minerFee = stepCount > 16 ? c_stepFee : 0;
bigint minerFee = stepCount > 16 ? m_fees.m_stepFee : 0;
bigint voidFee = 0;
auto rawInst = mem(curPC);
@ -650,21 +698,21 @@ void State::execute(Address _myAddress, Address _txSender, u256 _txValue, u256 _
case Instruction::STORE:
require(2);
if (!mem(stack.back()) && stack[stack.size() - 2])
voidFee += c_memoryFee;
voidFee += m_fees.m_memoryFee;
if (mem(stack.back()) && !stack[stack.size() - 2])
voidFee -= c_memoryFee;
voidFee -= m_fees.m_memoryFee;
// continue on to...
case Instruction::LOAD:
minerFee += c_dataFee;
minerFee += m_fees.m_dataFee;
break;
case Instruction::EXTRO:
case Instruction::BALANCE:
minerFee += c_extroFee;
minerFee += m_fees.m_extroFee;
break;
case Instruction::MKTX:
minerFee += c_txFee;
minerFee += m_fees.m_txFee;
break;
case Instruction::SHA256:
@ -674,7 +722,7 @@ void State::execute(Address _myAddress, Address _txSender, u256 _txValue, u256 _
case Instruction::ECSIGN:
case Instruction::ECRECOVER:
case Instruction::ECVALID:
minerFee += c_cryptoFee;
minerFee += m_fees.m_cryptoFee;
break;
default:
break;
@ -779,9 +827,6 @@ void State::execute(Address _myAddress, Address _txSender, u256 _txValue, u256 _
case Instruction::TXVALUE:
stack.push_back(_txValue);
break;
case Instruction::TXFEE:
stack.push_back(_txFee);
break;
case Instruction::TXDATAN:
stack.push_back(_txData.size());
break;
@ -1069,8 +1114,6 @@ void State::execute(Address _myAddress, Address _txSender, u256 _txValue, u256 _
stack.pop_back();
t.value = stack.back();
stack.pop_back();
t.fee = stack.back();
stack.pop_back();
auto itemCount = stack.back();
stack.pop_back();
@ -1092,7 +1135,7 @@ void State::execute(Address _myAddress, Address _txSender, u256 _txValue, u256 _
{
require(1);
Address dest = asAddress(stack.back());
u256 minusVoidFee = myMemory.size() * c_memoryFee;
u256 minusVoidFee = myMemory.size() * m_fees.m_memoryFee;
addBalance(dest, balance(_myAddress) + minusVoidFee);
m_cache[_myAddress].kill();
// ...follow through to...

40
libethereum/State.h

@ -42,6 +42,21 @@ class BlockChain;
extern const u256 c_genesisDifficulty;
std::map<Address, AddressState> const& genesisState();
#define ETH_SENDER_PAYS_SETUP 1
struct FeeStructure
{
/// The fee structure. Values yet to be agreed on...
void setMultiplier(u256 _x); ///< The current block multiplier.
u256 m_stepFee;
u256 m_dataFee;
u256 m_memoryFee;
u256 m_extroFee;
u256 m_cryptoFee;
u256 m_newContractFee;
u256 m_txFee;
};
/**
* @brief Model of the current state of the ledger.
* Maintains current ledger (m_current) as a fast hash-map. This is hashed only when required (i.e. to create or verify a block).
@ -53,6 +68,12 @@ public:
/// Construct state object.
State(Address _coinbaseAddress, Overlay const& _db);
/// Copy state object.
State(State const& _s);
/// Copy state object.
State& operator=(State const& _s);
/// Set the coinbase address for any transactions we do.
/// This causes a complete reset of current block.
void setAddress(Address _coinbaseAddress) { m_ourAddress = _coinbaseAddress; resetCurrent(); }
@ -146,6 +167,12 @@ public:
/// This might throw.
u256 playback(bytesConstRef _block, BlockInfo const& _bi, BlockInfo const& _parent, BlockInfo const& _grandParent, bool _fullCommit);
/// Get the fee associated for a contract created with the given data.
u256 fee(uint _dataCount) const { return m_fees.m_memoryFee * _dataCount + m_fees.m_newContractFee; }
/// Get the fee associated for a normal transaction.
u256 fee() const { return m_fees.m_txFee; }
private:
/// Fee-adder on destruction RAII class.
struct MinerFeeAdder
@ -177,7 +204,7 @@ private:
void executeBare(Transaction const& _t, Address _sender);
/// Execute a contract transaction.
void execute(Address _myAddress, Address _txSender, u256 _txValue, u256 _txFee, u256s const& _txData, u256* o_totalFee);
void execute(Address _myAddress, Address _txSender, u256 _txValue, u256s const& _txData, u256* o_totalFee);
/// Sets m_currentBlock to a clean state, (i.e. no change from m_previousBlock).
void resetCurrent();
@ -200,15 +227,8 @@ private:
Dagger m_dagger;
/// The fee structure. Values yet to be agreed on...
static const u256 c_stepFee;
static const u256 c_dataFee;
static const u256 c_memoryFee;
static const u256 c_extroFee;
static const u256 c_cryptoFee;
static const u256 c_newContractFee;
static const u256 c_txFee;
static const u256 c_blockReward;
FeeStructure m_fees;
u256 m_blockReward;
static std::string c_defaultPath;

11
libethereum/Transaction.cpp

@ -32,11 +32,10 @@ Transaction::Transaction(bytesConstRef _rlpData)
nonce = rlp[0].toInt<u256>();
receiveAddress = rlp[1].toHash<Address>();
value = rlp[2].toInt<u256>();
fee = rlp[3].toInt<u256>();
data.reserve(rlp[4].itemCountStrict());
for (auto const& i: rlp[4])
data.reserve(rlp[3].itemCountStrict());
for (auto const& i: rlp[3])
data.push_back(i.toInt<u256>());
vrs = Signature{ rlp[5].toInt<byte>(), rlp[6].toInt<u256>(), rlp[7].toInt<u256>() };
vrs = Signature{ rlp[4].toInt<byte>(), rlp[5].toInt<u256>(), rlp[6].toInt<u256>() };
}
Address Transaction::sender() const
@ -91,8 +90,8 @@ void Transaction::sign(Secret _priv)
void Transaction::fillStream(RLPStream& _s, bool _sig) const
{
_s.appendList(_sig ? 8 : 5);
_s << nonce << receiveAddress << value << fee << data;
_s.appendList(_sig ? 7 : 4);
_s << nonce << receiveAddress << value << data;
if (_sig)
_s << vrs.v << vrs.r << vrs.s;
}

3
libethereum/Transaction.h

@ -34,7 +34,7 @@ struct Signature
u256 s;
};
// [ nonce, receiving_address, value, fee, [ data item 0, data item 1 ... data item n ], v, r, s ]
// [ nonce, receiving_address, value, [ data item 0, data item 1 ... data item n ], v, r, s ]
struct Transaction
{
Transaction() {}
@ -44,7 +44,6 @@ struct Transaction
u256 nonce;
Address receiveAddress;
u256 value;
u256 fee;
u256s data;
Signature vrs;

2
libethereum/UPnP.cpp

@ -117,7 +117,7 @@ int UPnP::addRedirect(char const* addr, int port)
// Failed - now try (random external, port internal) and cycle up to 10 times.
for (uint i = 0; i < 10; ++i)
{
port = random() % 65535 - 1024 + 1024;
port = rand() % 65535 - 1024 + 1024;
sprintf(port_str, "%d", port);
if (!UPNP_AddPortMapping(m_urls->controlURL, m_data->first.servicetype, NULL, port_str, addr, "ethereum", "TCP", NULL, NULL))
return port;

1
test/crypto.cpp

@ -41,7 +41,6 @@ int cryptoTest()
Transaction t;
t.nonce = 0;
t.fee = 0;
t.value = 1; // 1 wei.
t.receiveAddress = toAddress(sha3("123"));

4
test/peer.cpp

@ -20,6 +20,8 @@
* Peer Network test functions.
*/
#include <chrono>
#include <thread>
#include <BlockChain.h>
#include <PeerNetwork.h>
using namespace std;
@ -53,7 +55,7 @@ int peerTest(int argc, char** argv)
for (int i = 0; ; ++i)
{
usleep(100000);
this_thread::sleep_for(chrono::milliseconds(100));
pn.process(ch);
if (!(i % 10))
pn.pingAll();

1
test/state.cpp

@ -62,7 +62,6 @@ int stateTest()
{
Transaction t;
t.nonce = s.transactionsFrom(myMiner.address());
t.fee = 0;
t.value = 1000; // 1e3 wei.
t.receiveAddress = me.address();
t.sign(myMiner.secret());

Loading…
Cancel
Save