Browse Source

Added client API & prototypal GUI.

cl-refactor
Gav Wood 11 years ago
parent
commit
30cbe3be1e
  1. 17
      alephzero/Main.cpp
  2. 27
      alephzero/Main.h
  3. 149
      alephzero/Main.ui
  4. 25
      alephzero/alephzero.pro
  5. 11
      alephzero/main.cpp
  6. 24
      eth/main.cpp
  7. 121
      libethereum/Client.cpp
  8. 68
      libethereum/Client.h
  9. 3
      libethereum/Common.h
  10. 114
      libethereum/PeerNetwork.cpp
  11. 44
      libethereum/PeerNetwork.h
  12. 11
      libethereum/RLP.h
  13. 1
      libethereum/vector_ref.h
  14. 4
      test/peer.cpp

17
alephzero/Main.cpp

@ -0,0 +1,17 @@
#include "Main.h"
#include "ui_Main.h"
Main::Main(QWidget *parent) :
QDialog(parent),
ui(new Ui::Main)
{
setWindowFlags(Qt::Window);
ui->setupUi(this);
ui->transactions->setHtml("Hello world!");
}
Main::~Main()
{
delete ui;
}

27
alephzero/Main.h

@ -0,0 +1,27 @@
#ifndef MAIN_H
#define MAIN_H
#include <QDialog>
namespace Ui {
class Main;
}
class Main : public QDialog
{
Q_OBJECT
public:
explicit Main(QWidget *parent = 0);
~Main();
private slots:
void on_connect_clicked();
private:
Client c;
Ui::Main *ui;
};
#endif // MAIN_H

149
alephzero/Main.ui

@ -0,0 +1,149 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Main</class>
<widget class="QDialog" name="Main">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>787</width>
<height>555</height>
</rect>
</property>
<property name="windowTitle">
<string>Main</string>
</property>
<property name="sizeGripEnabled">
<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="connect">
<property name="text">
<string>Connect</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="value">
<property name="suffix">
<string> wei</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="fee">
<property name="suffix">
<string>)</string>
</property>
<property name="prefix">
<string>(fee </string>
</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>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>205</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QToolButton" name="mine">
<property name="text">
<string>Mine</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QWidget" name="mineProgress" native="true"/>
</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="QListView" name="accounts">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
</widget>
<widget class="QTextEdit" name="transactions">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</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>
<widget class="QLabel" name="balance">
<property name="text">
<string>0 wei</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="address"/>
</item>
<item>
<widget class="QLabel" name="peers">
<property name="text">
<string>0 peers</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>

25
alephzero/alephzero.pro

@ -0,0 +1,25 @@
#-------------------------------------------------
#
# Project created by QtCreator 2014-01-22T11:47:38
#
#-------------------------------------------------
QT += core gui widgets
TARGET = alephzero
TEMPLATE = app
QMAKE_LIBDIR += ../../cpp-ethereum-build/libethereum ../../secp256k1 ../../cryptopp562
LIBS += -lethereum -lsecp256k1 -lleveldb -lcryptopp -lgmp -lboost_system -lboost_filesystem
SOURCES += main.cpp\
Main.cpp
HEADERS += Main.h
FORMS += Main.ui
INCLUDEPATH = ../../secp256k1/include ../../cryptopp562

11
alephzero/main.cpp

@ -0,0 +1,11 @@
#include "Main.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Main w;
w.show();
return a.exec();
}

24
eth/main.cpp

@ -28,9 +28,27 @@ using namespace eth;
int main()
{
short listenPort = 30303;
string remoteHost;
short remotePort = 30303;
// Our address.
h256 privkey = sha3("123");
Address us = toAddress(privkey); // TODO: should be loaded from config file/set at command-line.
Address us; // TODO: should be loaded from config file
for (int i = 1; i < argc; ++i)
{
string arg = argv[i];
if (arg == "-l" && i + 1 < argc)
listenPort = atoi(argv[++i]);
else if (arg == "-r" && i + 1 < argc)
remoteHost = argv[++i];
else if (arg == "-p" && i + 1 < argc)
remotePort = atoi(argv[++i]);
else if (arg == "-a" && i + 1 < argc)
us = h256(fromUserHex(argv[++i]));
else
remoteHost = argv[i];
}
BlockChain bc; // Maintains block database.
TransactionQueue tq; // Maintains list of incoming transactions not yet on the block chain.
@ -43,7 +61,7 @@ int main()
s.sync(bc);
s.sync(tq);
PeerServer net(0, 30303); // TODO: Implement - should run in background and send us events when blocks found and allow us to send blocks as required.
PeerServer net(bc, 0, 30303); // TODO: Implement - should run in background and send us events when blocks found and allow us to send blocks as required.
while (true)
{
// Process network events.

121
libethereum/Client.cpp

@ -0,0 +1,121 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Foobar is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file Client.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
#include "Common.h"
#include "Client.h"
using namespace std;
using namespace eth;
Client::Client(std::string const& _dbPath):
m_bc(_dbPath),
m_stateDB(State::openDB(_dbPath)),
m_s(m_stateDB)
{
Defaults::setDBPath(_dbPath);
// Synchronise the state according to the block chain - i.e. replay all transactions in block chain, in order.
// In practise this won't need to be done since the State DB will contain the keys for the tries for most recent (and many old) blocks.
// TODO: currently it contains keys for *all* blocks. Make it remove old ones.
s.sync(bc);
s.sync(tq);
m_work = new thread([&](){ while (m_workState != Deleting) work(); m_workState = Deleted; });
}
Client::~Client()
{
if (m_workState == Active)
m_workState = Deleting;
while (m_workState != Deleted)
usleep(10000);
}
void Client::transact(Address _dest, u256 _amount, u256 _fee, u256s _data = u256s(), Secret _secret)
{
}
BlockChain const& Client::blockChain() const
{
}
TransactionQueue const& Client::transactionQueue() const
{
}
unsigned Client::peerCount() const
{
}
void Client::startNetwork(short _listenPort = 30303, std::string const& _seedHost, short _port = 30303)
{
if (m_net)
return;
m_net = new PeerServer(m_bc, 0, _listenPort);
if (_seedHost.size())
m_net->connect(_seedHost, _port);
}
void Client::stopNetwork()
{
delete m_net;
m_net = nullptr;
}
void Client::startMining()
{
m_doMine = true;
}
void Client::stopMining()
{
m_doMine = false;
}
std::pair<unsigned, unsigned> Client::miningProgress() const
{
}
void Client::work(string const& _seedHost, short _port)
{
// 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.
m_net->process(m_bc, m_tq);
// Synchronise state to block chain.
// This should remove any transactions on our queue that are included within our state.
// It also guarantees that the state reflects the longest (valid!) chain on the block chain.
// This might mean reverting to an earlier state and replaying some blocks, or, (worst-case:
// if there are no checkpoints before our fork) reverting to the genesis block and replaying
// all blocks.
m_s.sync(m_bc); // Resynchronise state with block chain & trans
m_s.sync(m_tq);
if (m_doMine)
{
// Mine for a while.
bytes b = s.mine(100);
if (b.size())
// Import block.
bc.attemptImport(b, stateDB);
}
}

68
libethereum/Client.h

@ -0,0 +1,68 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Foobar is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file Client.h
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
#pragma once
#include <thread>
#include <mutex>
#include "Common.h"
#include "BlockChain.h"
#include "TransactionQueue.h"
#include "State.h"
#include "PeerNetwork.h"
namespace eth
{
class Client
{
public:
Client(std::string const& _dbPath);
~Client();
void transact(Address _dest, u256 _amount, u256 _fee, u256s _data = u256s(), Secret _secret);
BlockChain const& blockChain() const;
TransactionQueue const& transactionQueue() const;
unsigned peerCount() const;
void startNetwork(short _listenPort = 30303, std::string const& _seedHost, short _port = 30303);
void stopNetwork();
void startMining();
void stopMining();
std::pair<unsigned, unsigned> miningProgress() const;
private:
void work();
BlockChain m_bc; ///< Maintains block database.
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.
PeerServer* m_net = nullptr; ///< Should run in background and send us events when blocks found and allow us to send blocks as required.
std::thread* m_work; ///< The work thread.
enum { Active = 0, Deleting, Deleted } m_workState = Active;
bool m_doMine = false; ///< Are we supposed to be mining?
};
}

3
libethereum/Common.h

@ -74,6 +74,7 @@ public:
FixedHash() { m_data.fill(0); }
FixedHash(Arith const& _arith) { toBigEndian(_arith, m_data); }
explicit FixedHash(bytes const& _b) { memcpy(m_data.data(), _b.data(), min<uint>(_b.size(), N)); }
operator Arith() const { return fromBigEndian<Arith>(m_data); }
@ -97,7 +98,7 @@ public:
byte* data() { return m_data.data(); }
byte const* data() const { return m_data.data(); }
bytes asBytes() const { return bytes(data(), data() + 32); }
bytes asBytes() const { return bytes(data(), data() + N); }
private:
std::array<byte, N> m_data;

114
libethereum/PeerNetwork.cpp

@ -20,11 +20,12 @@
*/
#include "Common.h"
#include "BlockChain.h"
#include "PeerNetwork.h"
using namespace std;
using namespace eth;
PeerSession::PeerSession(bi::tcp::socket _socket, uint _rNId): m_socket(std::move(_socket)), m_reqNetworkId(_rNId)
PeerSession::PeerSession(PeerServer* _s, bi::tcp::socket _socket, uint _rNId): m_server(_s), m_socket(std::move(_socket)), m_reqNetworkId(_rNId)
{
}
@ -60,6 +61,61 @@ bool PeerSession::interpret(RLP const& _r)
case Pong:
cout << "Latency: " << chrono::duration_cast<chrono::milliseconds>(std::chrono::steady_clock::now() - m_ping).count() << " ms" << endl;
break;
case GetPeers:
{
std::vector<bi::tcp::endpoint> peers = m_server->peers();
RLPStream s;
prep(s).appendList(2);
s << Peers;
s.appendList(peers.size());
for (auto i: peers)
s.appendList(2) << i.address().to_v4().to_bytes() << i.port();
sealAndSend(s);
break;
}
case Peers:
for (auto i: _r[1])
{
auto ep = bi::tcp::endpoint(bi::address_v4(i[0].toArray<byte, 4>()), i[1].toInt<short>());
m_server->m_incomingPeers.push_back(ep);
cout << "New peer: " << ep << endl;
}
break;
case Transactions:
for (auto i: _r[1])
m_server->m_incomingTransactions.push_back(i.data().toBytes());
break;
case Blocks:
for (auto i: _r[1])
m_server->m_incomingBlocks.push_back(i.data().toBytes());
break;
case GetChain:
{
h256 parent = _r[1].toHash<h256>();
// return 256 block max.
uint count = (uint)min<bigint>(_r[1].toInt<bigint>(), 256);
h256 latest = m_server->m_chain->currentHash();
uint latestNumber = 0;
uint parentNumber = 0;
if (m_server->m_chain->details(parent))
{
latestNumber = m_server->m_chain->details(latest).number;
parentNumber = m_server->m_chain->details(parent).number;
}
count = min<uint>(latestNumber - parentNumber, count);
RLPStream s;
prep(s);
s.appendList(2);
s.append(Blocks);
s.appendList(count);
uint startNumber = m_server->m_chain->details(parent).number + count;
auto h = m_server->m_chain->currentHash();
for (uint n = latestNumber; h != parent; n--, h = m_server->m_chain->details(h).parent)
if (m_server->m_chain->details(h).number <= startNumber)
s.appendRaw(m_server->m_chain->block(h));
sealAndSend(s);
break;
}
default:
break;
}
@ -98,9 +154,7 @@ void PeerSession::send(bytes& _msg)
{
std::shared_ptr<bytes> buffer = std::make_shared<bytes>();
swap(*buffer, _msg);
ba::async_write(m_socket, ba::buffer(*buffer), [=](boost::system::error_code ec, std::size_t length)
{
});
ba::async_write(m_socket, ba::buffer(*buffer), [=](boost::system::error_code ec, std::size_t length) {});
}
void PeerSession::disconnect()
@ -153,7 +207,8 @@ void PeerSession::doRead()
});
}
PeerServer::PeerServer(uint _networkId, short _port):
PeerServer::PeerServer(BlockChain const& _ch, uint _networkId, short _port):
m_chain(&_ch),
m_acceptor(m_ioService, bi::tcp::endpoint(bi::tcp::v4(), _port)),
m_socket(m_ioService),
m_requiredNetworkId(_networkId)
@ -168,6 +223,21 @@ PeerServer::PeerServer(uint _networkId):
{
}
std::vector<bi::tcp::endpoint> PeerServer::peers()
{
std::vector<bi::tcp::endpoint> ret;
bool haveLocal = false;
for (auto i: m_peers)
if (auto j = i.lock())
{
if (!haveLocal)
ret.push_back(j->m_socket.local_endpoint());
haveLocal = true;
ret.push_back(j->m_socket.remote_endpoint());
}
return ret;
}
void PeerServer::doAccept()
{
cout << "Listening on " << m_acceptor.local_endpoint() << endl;
@ -176,7 +246,7 @@ void PeerServer::doAccept()
if (!ec)
{
std::cout << "Accepted connection from " << m_socket.remote_endpoint() << std::endl;
auto p = std::make_shared<PeerSession>(std::move(m_socket), m_requiredNetworkId);
auto p = std::make_shared<PeerSession>(this, std::move(m_socket), m_requiredNetworkId);
m_peers.push_back(p);
p->start();
}
@ -192,7 +262,7 @@ bool PeerServer::connect(string const& _addr, uint _port)
{
bi::tcp::socket s(m_ioService);
boost::asio::connect(s, resolver.resolve({ _addr, toString(_port) }));
auto p = make_shared<PeerSession>(std::move(s), m_requiredNetworkId);
auto p = make_shared<PeerSession>(this, std::move(s), m_requiredNetworkId);
m_peers.push_back(p);
cout << "Connected." << endl;
p->start();
@ -205,22 +275,15 @@ bool PeerServer::connect(string const& _addr, uint _port)
}
}
void PeerServer::process()
void PeerServer::process(BlockChain& _bc, TransactionQueue const& _tq)
{
m_ioService.poll();
// TODO: Gather all transactions, blocks & peers.
}
void PeerServer::pingAll()
{
for (auto& i: m_peers)
if (auto j = i.lock())
j->ping();
}
void PeerServer::sync(BlockChain& _bc, TransactionQueue const& _tq)
{
/*
for (auto i = m_peers.begin(); i != m_peers.end();)
if (auto j = i->lock())
{}
else
i = m_peers.erase(i);
/*
while (incomingData())
{
// import new block
@ -229,5 +292,12 @@ void PeerServer::sync(BlockChain& _bc, TransactionQueue const& _tq)
handleMessage(data);
popIncoming();
}
*/
*/
}
void PeerServer::pingAll()
{
for (auto& i: m_peers)
if (auto j = i.lock())
j->ping();
}

44
libethereum/PeerNetwork.h

@ -36,6 +36,7 @@ namespace eth
class BlockChain;
class TransactionQueue;
class BlockChain;
enum PacketType
{
@ -50,10 +51,14 @@ enum PacketType
GetChain
};
class PeerServer;
class PeerSession: public std::enable_shared_from_this<PeerSession>
{
friend class PeerServer;
public:
PeerSession(bi::tcp::socket _socket, uint _rNId);
PeerSession(PeerServer* _server, bi::tcp::socket _socket, uint _rNId);
~PeerSession();
void start();
@ -70,6 +75,7 @@ private:
void sealAndSend(RLPStream& _s);
void send(bytes& _msg);
PeerServer* m_server;
bi::tcp::socket m_socket;
std::array<byte, 65536> m_data;
@ -79,48 +85,58 @@ private:
uint m_networkId;
uint m_reqNetworkId;
std::vector<bytes> m_incomingTransactions;
std::vector<bytes> m_incomingBlocks;
std::vector<bi::tcp::endpoint> m_incomingPeers;
std::chrono::steady_clock::time_point m_ping;
};
class PeerServer
{
friend class PeerSession;
public:
/// Start server, listening for connections on the given port.
PeerServer(uint _networkId, short _port);
PeerServer(BlockChain const& _ch, uint _networkId, short _port);
/// Start server, but don't listen.
PeerServer(uint _networkId);
/// Conduct I/O, polling, syncing, whatever.
/// Ideally all time-consuming I/O is done in a background thread, but you get this call every 100ms or so anyway.
void process();
/// Connect to a peer explicitly.
bool connect(std::string const& _addr = "127.0.0.1", uint _port = 30303);
/// Sync with the BlockChain. It might contain one of our mined blocks, we might have new candidates from the network.
void sync(BlockChain& _bc, TransactionQueue const&);
/// Conduct I/O, polling, syncing, whatever.
/// Ideally all time-consuming I/O is done in a background thread, but you get this call every 100ms or so anyway.
void process(BlockChain& _bc, TransactionQueue const&);
/// Get an incoming transaction from the queue. @returns bytes() if nothing waiting.
std::vector<bytes> const& incomingTransactions() { return m_incomingTransactions; }
/// Get an incoming transaction from the queue. @returns bytes() if nothing waiting.
void incomingTransactions(std::vector<bytes>& o_out) { swap(o_out, m_incomingTransactions); m_incomingTransactions.clear(); }
/// Get an incoming transaction from the queue. @returns bytes() if nothing waiting.
bytes const& incomingTransaction() { return NullBytes; }
void incomingBlocks(std::vector<bytes>& o_out) { swap(o_out, m_blocks); m_blocks.clear(); }
/// Remove incoming transaction from the queue. Make sure you've finished with the data from any previous incomingTransaction() calls.
void popIncomingTransaction() {}
/// Get number of peers connected.
unsigned peerCount() const { return m_peers.size(); }
/// Remove incoming transactions from the queue.
void clearIncomingTransactions() {}
void pingAll();
private:
void doAccept();
std::vector<bi::tcp::endpoint> peers();
BlockChain const* m_chain = nullptr;
ba::io_service m_ioService;
bi::tcp::acceptor m_acceptor;
bi::tcp::socket m_socket;
uint m_requiredNetworkId;
std::vector<std::weak_ptr<PeerSession>> m_peers;
std::vector<bytes> m_incomingTransactions;
std::vector<bytes> m_incomingBlocks;
std::vector<bi::tcp::endpoint> m_incomingPeers;
};

11
libethereum/RLP.h

@ -23,6 +23,8 @@
#pragma once
#include <vector>
#include <array>
#include <exception>
#include <iostream>
#include <iomanip>
@ -158,9 +160,10 @@ public:
/// Best-effort conversion operators.
explicit operator std::string() const { return toString(); }
explicit operator RLPs() const { return toList(); }
explicit operator uint() const { return toSlimInt(); }
explicit operator u256() const { return toFatInt(); }
explicit operator bigint() const { return toBigInt(); }
explicit operator byte() const { return toInt<byte>(); }
explicit operator uint() const { return toInt<uint>(); }
explicit operator u256() const { return toInt<u256>(); }
explicit operator bigint() const { return toInt<bigint>(); }
template <unsigned _N> explicit operator FixedHash<_N>() const { return toHash<FixedHash<_N>>(); }
/// Converts to bytearray. @returns the empty byte array if not a string.
@ -173,6 +176,7 @@ public:
std::string toStringStrict() const { if (!isString()) throw BadCast(); return payload().cropped(0, items()).toString(); }
template <class T> std::vector<T> toVector() const { std::vector<T> ret; if (isList()) { ret.reserve(itemCount()); for (auto const& i: *this) ret.push_back((T)i); } return ret; }
template <class T, size_t N> std::array<T, N> toArray() const { std::array<T, N> ret; if (itemCount() != N) throw BadCast(); if (isList()) for (uint i = 0; i < N; ++i) ret[i] = (T)operator[](i); return ret; }
/// Int conversion flags
enum
@ -321,6 +325,7 @@ public:
RLPStream& operator<<(std::string const& _s) { return appendString(_s); }
RLPStream& operator<<(RLP const& _i) { return appendRaw(_i); }
template <class _T> RLPStream& operator<<(std::vector<_T> const& _s) { appendList(_s.size()); for (auto const& i: _s) append(i); return *this; }
template <class _T, size_t S> RLPStream& operator<<(std::array<_T, S> const& _s) { appendList(_s.size()); for (auto const& i: _s) append(i); return *this; }
/// Read the byte stream.
bytes const& out() const { return m_out; }

1
libethereum/vector_ref.h

@ -35,6 +35,7 @@ public:
bool contentsEqual(std::vector<_T> const& _c) const { return _c.size() == m_count && !memcmp(_c.data(), m_data, m_count); }
std::vector<_T> toVector() const { return std::vector<_T>(m_data, m_data + m_count); }
std::vector<unsigned char> toBytes() const { return std::vector<unsigned char>((unsigned char const*)m_data, m_data + m_count * sizeof(_T)); }
std::string toString() const { return std::string((char const*)m_data, ((char const*)m_data) + m_count); }
template <class _T2> operator vector_ref<_T2>() const { assert(m_count * sizeof(_T) / sizeof(_T2) * sizeof(_T2) / sizeof(_T) == m_count); return vector_ref<_T2>((_T2*)m_data, m_count * sizeof(_T) / sizeof(_T2)); }

4
test/peer.cpp

@ -20,6 +20,7 @@
* Peer Network test functions.
*/
#include <BlockChain.h>
#include <PeerNetwork.h>
using namespace std;
using namespace eth;
@ -44,7 +45,8 @@ int peerTest(int argc, char** argv)
remoteHost = argv[i];
}
PeerServer pn(0, listenPort);
BlockChain ch("/tmp");
PeerServer pn(ch, 0, listenPort);
if (!remoteHost.empty())
pn.connect(remoteHost, remotePort);

Loading…
Cancel
Save