diff --git a/SConstruct b/SConstruct
index a656f1f01..ef0806738 100644
--- a/SConstruct
+++ b/SConstruct
@@ -52,7 +52,6 @@ DB_SRCS = glob.glob('database/*.c') + glob.glob('database/*.cpp')
JSON_SRCS = glob.glob('json/*.cpp')
NEWCOIN_SRCS = glob.glob('src/*.cpp')
PROTO_SRCS = env.Protoc([], 'src/newcoin.proto', PROTOCOUTDIR='obj', PROTOCPYTHONOUTDIR=None)
-UTIL_SRCS = glob.glob('util/*.cpp')
env.Clean(PROTO_SRCS, 'site_scons/site_tools/protoc.pyc')
@@ -62,7 +61,7 @@ UNUSED_SRCS = ['src/HttpReply.cpp', 'src/ValidationCollection.cpp']
for file in UNUSED_SRCS:
NEWCOIN_SRCS.remove(file)
-NEWCOIN_SRCS += DB_SRCS + JSON_SRCS + UTIL_SRCS
+NEWCOIN_SRCS += DB_SRCS + JSON_SRCS
# Derive the object files from the source files.
NEWCOIN_OBJS = []
diff --git a/db layout.txt b/db layout.txt
deleted file mode 100644
index 773531c97..000000000
--- a/db layout.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-// need to make this compatible with at least SQLite and Mysql
-
-// SQLite
-CREATE TABLE UNL (Hanko BLOB PRIMARY KEY, PubKey BLOB);
-CREATE TABLE Transactions (TransactionID INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, From BLOB, Dest BLOB, Amount BIGINT UNSIGNED, LedgerIndex INT UNSIGNED, SeqNum INT, PubKey BLOB, Sig BLOB);
-CREATE TABLE Ledgers (LedgerID INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, LedgerIndex INT UNSIGNED, Hash BLOB, ParentHash BLOB,FeeHeld BIGINT UNSIGNED);
-CREATE TABLE Validations(ValidationID INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, LedgerIndex INT UNSIGNED, Hash BLOB, Hanko BLOB, SeqNum INT UNSIGNED, Sig BLOB, WeCare TINYINT);
-CREATE TABLE LedgerTransactionMap (LedgerID INT UNSIGNED, TransactionID INT UNSIGNED, Include TINYINT);
-CREATE TABLE LedgerAccountMap(LedgerID INT UNSIGNED,AccountID INT UNSIGNED);
-CREATE TABLE Accounts (AccountID INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, Address BLOB, Amount BIGINT UNSIGNED, SeqNum INT);
-CREATE TABLE AcceptedLedgers (LedgerIndex INT UNSIGNED PRIMARY KEY, LedgerID INT UNSIGNED);
-
-CREATE TABLE Wallet (Address BLOB,PubKey BLOB,PrivateKey BLOB,int SeqNum);
-CREATE TABLE YourValidations(LedgerIndex INT UNSIGNED PRIMARY KEY, Hash BLOB, SeqNum INT UNSIGNED );
-
-
-
-// MYSQL
-drop database if exists newcoin;
-CREATE DATABASE newcoin;
-use newcoin;
-CREATE TABLE UNL (Hanko BINARY(20) PRIMARY KEY, PubKey BINARY(128));
-CREATE TABLE Transactions (TransactionID INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, From BINARY(20), Dest BINARY(20), Amount BIGINT UNSIGNED, LedgerIndex INT UNSIGNED, SeqNum INT, PubKey BINARY(64), Sig BINARY(32));
-CREATE TABLE Ledgers (LedgerID INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, LedgerIndex INT UNSIGNED, Hash BINARY(32), ParentHash BINARY(32),FeeHeld BIGINT UNSIGNED); //, Accepted TINYINT
-CREATE TABLE Validations(LedgerIndex INT UNSIGNED, Hash BINARY(32), Hanko BINARY(20), SeqNum INT UNSIGNED, Sig BINARY(32), WeCare TINYINT);
-CREATE TABLE LedgerTransactionMap (LedgerID INT UNSIGNED, TransactionID INT UNSIGNED, Include TINYINT);
-CREATE TABLE LedgerAccountMap(LedgerID INT UNSIGNED,AccountID INT UNSIGNED);
-CREATE TABLE Accounts (AccountID INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, Address BINARY(20), Amount BIGINT UNSIGNED, SeqNum INT);
-CREATE TABLE AcceptedLedgers (LedgerIndex INT UNSIGNED PRIMARY KEY, LedgerID INT UNSIGNED);
diff --git a/nodes.xml b/nodes.xml
deleted file mode 100644
index b8b1e8fb5..000000000
--- a/nodes.xml
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/src/AccountState.cpp b/src/AccountState.cpp
index a3a61d267..88307dbb3 100644
--- a/src/AccountState.cpp
+++ b/src/AccountState.cpp
@@ -9,7 +9,7 @@
AccountState::AccountState(const NewcoinAddress& id) : mAccountID(id), mValid(false)
{
- if (!id.IsValid()) return;
+ if (!id.isValid()) return;
mLedgerEntry = boost::make_shared(ltACCOUNT_ROOT);
mLedgerEntry->setIndex(Ledger::getAccountRootIndex(id));
mLedgerEntry->setIFieldAccount(sfAccount, id);
@@ -21,7 +21,7 @@ AccountState::AccountState(SerializedLedgerEntry::pointer ledgerEntry) : mLedger
if (!mLedgerEntry) return;
if (mLedgerEntry->getType()!=ltACCOUNT_ROOT) return;
mAccountID = mLedgerEntry->getValueFieldAccount(sfAccount);
- if (mAccountID.IsValid()) mValid = true;
+ if (mAccountID.isValid()) mValid = true;
}
void AccountState::addJson(Json::Value& val)
diff --git a/src/Application.cpp b/src/Application.cpp
index f4ebf63fd..23bb43b94 100644
--- a/src/Application.cpp
+++ b/src/Application.cpp
@@ -73,8 +73,8 @@ void Application::run()
//
// Begin validation and ip maintenance.
+ // - Wallet maintains local information: including identity and network connection persistency information.
//
-
mWallet.start();
//
@@ -93,10 +93,12 @@ void Application::run()
mRPCDoor=new RPCDoor(mIOService);
}//else BOOST_LOG_TRIVIAL(info) << "No RPC Port set. Not listening for commands.";
- mConnectionPool.connectToNetwork(mKnownNodes, mIOService);
- mTimingService.start(mIOService);
+ //
+ // Begin connectting to network.
+ //
+ mConnectionPool.start();
- std::cout << "Before Run." << std::endl;
+ mTimingService.start(mIOService);
// Temporary root account will be ["This is my payphrase."]:0
NewcoinAddress rootFamilySeed; // Hold the 128 password.
diff --git a/src/Application.h b/src/Application.h
index 76bb5718c..b1023b1ea 100644
--- a/src/Application.h
+++ b/src/Application.h
@@ -3,7 +3,6 @@
#include "UniqueNodeList.h"
#include "ConnectionPool.h"
-#include "KnownNodeList.h"
#include "TimingService.h"
#include "PubKeyCache.h"
#include "ScopedLock.h"
@@ -42,7 +41,6 @@ class Application
TimingService mTimingService;
UniqueNodeList mUNL;
- KnownNodeList mKnownNodes;
PubKeyCache mPKCache;
LedgerMaster mMasterLedger;
LedgerAcquireMaster mMasterLedgerAcquire;
diff --git a/src/Config.cpp b/src/Config.cpp
index 468ffea48..f8066f915 100644
--- a/src/Config.cpp
+++ b/src/Config.cpp
@@ -6,7 +6,7 @@
#include
#include
-#define CONFIG_FILE_NAME "newcoind.cfg"
+#define CONFIG_FILE_NAME SYSTEM_NAME "d.cfg" // newcoind.cfg
#define SECTION_PEER_IP "peer_ip"
#define SECTION_PEER_PORT "peer_port"
#define SECTION_RPC_IP "rpc_ip"
@@ -22,8 +22,7 @@ Config::Config()
NETWORK_START_TIME=1319844908;
-
- PEER_PORT=6561;
+ PEER_PORT=SYSTEM_PEER_PORT;
RPC_PORT=5001;
NUMBER_CONNECTIONS=30;
diff --git a/src/Config.h b/src/Config.h
index 0270c0a69..951c5817e 100644
--- a/src/Config.h
+++ b/src/Config.h
@@ -1,4 +1,11 @@
-#include "string"
+#ifndef __CONFIG__
+#define __CONFIG__
+
+#include
+
+#define SYSTEM_NAME "newcoin"
+
+const int SYSTEM_PEER_PORT=6561;
class Config
{
@@ -8,9 +15,7 @@ public:
std::string VERSION_STR;
// network parameters
-// std::string NETWORK_ID;
-// std::string NETWORK_DNS_SEEDS;
- int NETWORK_START_TIME; // The Unix time we start ledger 0
+ int NETWORK_START_TIME; // The Unix time we start ledger 0
int TRANSACTION_FEE_BASE;
int LEDGER_SECONDS;
int LEDGER_PROPOSAL_DELAY_SECONDS;
@@ -28,8 +33,6 @@ public:
// bool NODE_DUMB; // we are a 'dumb' client
// bool NODE_SMART; // we offer services to 'dumb' clients
-// std::string HANKO_PRIVATE;
-
// RPC parameters
std::string RPC_IP;
int RPC_PORT;
@@ -48,3 +51,4 @@ public:
};
extern Config theConfig;
+#endif
diff --git a/src/ConnectionPool.cpp b/src/ConnectionPool.cpp
index 5208a20b7..4fae2ac89 100644
--- a/src/ConnectionPool.cpp
+++ b/src/ConnectionPool.cpp
@@ -1,32 +1,163 @@
-#include
#include
+#include
#include "ConnectionPool.h"
#include "Config.h"
-#include "KnownNodeList.h"
#include "Peer.h"
#include "Application.h"
+#include "utils.h"
-ConnectionPool::ConnectionPool()
+ConnectionPool::ConnectionPool() :
+ iConnecting(0)
{ ; }
-void ConnectionPool::connectToNetwork(KnownNodeList& nodeList,boost::asio::io_service& io_service)
+void ConnectionPool::start()
{
- for(int n=0; nconnectTo(*node); // FIXME
- mPeers.push_back(peer);
-
+ Peer::pointer peer = pair.second;
+
+ if(!fromPeer || !(peer.get() == fromPeer))
+ peer->sendPacket(msg);
}
}
-/*
+
+// Inbound connection, false=reject
+// Reject addresses we already have in our table.
+// XXX Reject, if we have too many connections.
+bool ConnectionPool::peerAccepted(Peer::pointer peer, const std::string& strIp, int iPort)
+{
+ bool bAccept;
+ ipPort ip = make_pair(strIp, iPort);
+
+ boost::unordered_map::iterator it;
+
+ boost::mutex::scoped_lock sl(mPeerLock);
+
+ it = mIpMap.find(ip);
+
+ if (it == mIpMap.end())
+ {
+ // Did not find it. Not already connecting or connected.
+
+ std::cerr << "ConnectionPool::peerAccepted: " << ip.first << " " << ip.second << std::endl;
+ // Mark as connecting.
+ mIpMap[ip] = peer;
+ bAccept = true;
+ }
+ else
+ {
+ // Found it. Already connected or connecting.
+
+ bAccept = false;
+ }
+
+ return bAccept;
+}
+
+bool ConnectionPool::connectTo(const std::string& strIp, int iPort)
+{
+ ipPort ip = make_pair(strIp, iPort);
+
+ boost::unordered_map::iterator it;
+
+ boost::mutex::scoped_lock sl(mPeerLock);
+
+ it = mIpMap.find(ip);
+
+ if (it == mIpMap.end())
+ {
+ // Did not find it. Not already connecting or connected.
+
+ Peer::pointer peer(Peer::create(theApp->getIOService()));
+
+ mIpMap[ip] = peer;
+
+ peer->connect(strIp, iPort);
+ }
+ else
+ {
+ // Found it. Already connected.
+ std::cerr << "ConnectionPool::connectTo: Already connected: "
+ << strIp << " " << iPort << std::endl;
+ }
+
+ return true;
+}
+
+Json::Value ConnectionPool::getPeersJson()
+{
+ Json::Value ret(Json::arrayValue);
+
+ BOOST_FOREACH(naPeer pair, mConnectedMap)
+ {
+ Peer::pointer peer = pair.second;
+
+ ret.append(peer->getJson());
+ }
+
+ return ret;
+}
+
+void ConnectionPool::peerConnected(Peer::pointer peer)
+{
+ std::cerr << "ConnectionPool::peerConnected" << std::endl;
+}
+
+void ConnectionPool::peerDisconnected(Peer::pointer peer)
+{
+ std::cerr << "ConnectionPool::peerDisconnected: " << peer->mIpPort.first << " " << peer->mIpPort.second << std::endl;
+
+ boost::mutex::scoped_lock sl(mPeerLock);
+
+ // XXX Don't access member variable directly.
+ if (peer->mPublicKey.isValid())
+ {
+ boost::unordered_map::iterator itCm;
+
+ itCm = mConnectedMap.find(peer->mPublicKey);
+
+ if (itCm == mConnectedMap.end())
+ {
+ // Did not find it. Not already connecting or connected.
+ std::cerr << "Internal Error: peer connection was inconsistent." << std::endl;
+ // XXX Bad error.
+ }
+ else
+ {
+ // Found it. Delete it.
+ mConnectedMap.erase(itCm);
+ }
+ }
+
+ // XXX Don't access member variable directly.
+ boost::unordered_map::iterator itIp;
+
+ itIp = mIpMap.find(peer->mIpPort);
+
+ if (itIp == mIpMap.end())
+ {
+ // Did not find it. Not already connecting or connected.
+ std::cerr << "Internal Error: peer wasn't connected." << std::endl;
+ // XXX Bad error.
+ }
+ else
+ {
+ // Found it. Delete it.
+ mIpMap.erase(itIp);
+ }
+}
+
+#if 0
bool ConnectionPool::isMessageKnown(PackedMessage::pointer msg)
{
for(unsigned int n=0; nsendPacket(msg);
- }
-}
-
-bool ConnectionPool::addToMap(const uint160& hanko, Peer::pointer peer)
-{
- boost::mutex::scoped_lock sl(peerLock);
- return peerMap.insert(std::make_pair(hanko, peer)).second;
-}
-
-bool ConnectionPool::delFromMap(const uint160& hanko)
-{
- boost::mutex::scoped_lock sl(peerLock);
- std::map::iterator it=peerMap.find(hanko);
- if((it==peerMap.end()) || (it->first!=hanko)) return false;
- peerMap.erase(it);
- return true;
-}
-
-Peer::pointer ConnectionPool::findInMap(const uint160& hanko)
-{
- boost::mutex::scoped_lock sl(peerLock);
- std::map::iterator it=peerMap.find(hanko);
- if(it==peerMap.end()) return Peer::pointer();
- return it->second;
-}
-
-bool ConnectionPool::inMap(const uint160& hanko)
-{
- boost::mutex::scoped_lock sl(peerLock);
- return peerMap.find(hanko) != peerMap.end();
-}
-
-std::map ConnectionPool::getAllConnected()
-{
- boost::mutex::scoped_lock sl(peerLock);
- return peerMap;
-}
-
-bool ConnectionPool::connectTo(const std::string& host, const std::string& port)
-{
- try
- {
- boost::asio::ip::tcp::resolver res(theApp->getIOService());
- boost::asio::ip::tcp::resolver::query query(host.c_str(), port.c_str());
- boost::asio::ip::tcp::resolver::iterator it(res.resolve(query)), end;
-
- Peer::pointer peer(Peer::create(theApp->getIOService()));
- boost::system::error_code error = boost::asio::error::host_not_found;
- while (error && (it!=end))
- {
- peer->getSocket().close();
- peer->getSocket().connect(*it++, error);
- }
- if(error) return false;
- boost::mutex::scoped_lock sl(peerLock);
- mPeers.push_back(peer);
- peer->connected(boost::system::error_code());
- }
- catch (...)
- {
- return false;
- }
- return true;
-}
-
-Json::Value ConnectionPool::getPeersJson()
-{
- Json::Value ret(Json::arrayValue);
-
- BOOST_FOREACH(Peer::pointer peer, mPeers)
- {
- ret.append(peer->getJson());
- }
-
- return ret;
-}
// vim:ts=4
diff --git a/src/ConnectionPool.h b/src/ConnectionPool.h
index 5b577dbbd..b19c27af8 100644
--- a/src/ConnectionPool.h
+++ b/src/ConnectionPool.h
@@ -1,41 +1,65 @@
#ifndef __CONNECTION_POOL__
#define __CONNECTION_POOL__
-#include
#include
#include "Peer.h"
#include "PackedMessage.h"
#include "types.h"
-class KnownNodeList;
-
-/*
-This is the list of all the Peers we are currently connected to
-*/
+//
+// Access to the Newcoin network.
+//
class ConnectionPool
{
- boost::mutex peerLock;
- std::vector mPeers; // FIXME
- std::map peerMap;
- //std::vector > mBroadcastMessages;
+private:
+ boost::mutex mPeerLock;
+
+ typedef std::pair naPeer;
+
+ // Count of peers we are in progress of connecting to.
+ // We are in progress until we know their network public key.
+ int iConnecting;
+
+ // Peers we are connecting with and non-thin peers we are connected to.
+ boost::unordered_map mIpMap;
+
+ // Non-thin peers which we are connected to.
+ boost::unordered_map mConnectedMap;
public:
ConnectionPool();
- void connectToNetwork(KnownNodeList& nodeList, boost::asio::io_service& io_service);
+
+ // Begin enforcing connection policy.
+ void start();
+
+ // Send message to network.
void relayMessage(Peer* fromPeer, PackedMessage::pointer msg);
- //bool isMessageKnown(PackedMessage::pointer msg);
- // hanko->peer mapping functions
- bool inMap(const uint160& hanko);
- bool addToMap(const uint160& hanko, Peer::pointer peer);
- bool delFromMap(const uint160& hanko);
- Peer::pointer findInMap(const uint160& hanko);
- std::map getAllConnected();
+ // Manual connection request.
+ // Queue for immediate scanning.
+ bool connectTo(const std::string& strIp, int iPort);
- bool connectTo(const std::string& host, const std::string& port);
+ //
+ // Peer connectivity notification.
+ //
+
+ // Inbound connection, false=reject
+ bool peerAccepted(Peer::pointer peer, const std::string& strIp, int iPort);
+
+ // We know peers node public key.
+ void peerConnected(Peer::pointer peer);
+
+ // No longer connected.
+ void peerDisconnected(Peer::pointer peer);
Json::Value getPeersJson();
+
+#if 0
+ //std::vector > mBroadcastMessages;
+
+ bool isMessageKnown(PackedMessage::pointer msg);
+#endif
};
#endif
diff --git a/src/KnownNodeList.cpp b/src/KnownNodeList.cpp
deleted file mode 100644
index e170935bc..000000000
--- a/src/KnownNodeList.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-#include "KnownNodeList.h"
-#include "../util/pugixml.hpp"
-
-using namespace pugi;
-
-KnownNode::KnownNode(const char* ip,int port,int lastSeen,int lastTried)
- : mIP(ip), mPort(port), mLastSeen(lastSeen), mLastTried(lastTried)
-{
-
-}
-
-KnownNodeList::KnownNodeList()
-{
- mTriedIndex=0;
-}
-
-void KnownNodeList::load()
-{
- xml_document doc;
- xml_parse_result result = doc.load_file("nodes.xml");
- xml_node nodes=doc.child("nodes");
- for(xml_node child = nodes.first_child(); child; child = child.next_sibling())
- {
- mNodes.push_back(KnownNode(child.attribute("ip").value(),child.attribute("port").as_int(),child.attribute("last").as_int(),0));
- }
-}
-
-KnownNode* KnownNodeList::getNextNode()
-{
- if(mTriedIndex>=mNodes.size())
- {
- return(NULL);
- }else
- {
- mTriedIndex++;
- return(&(mNodes[mTriedIndex-1]));
- }
-}
diff --git a/src/KnownNodeList.h b/src/KnownNodeList.h
deleted file mode 100644
index 6609314cc..000000000
--- a/src/KnownNodeList.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef __KNOWNNODELIST__
-#define __KNOWNNODELIST__
-
-#include "vector"
-#include
-
-class KnownNode
-{
-public:
- std::string mIP;
- int mPort;
- int mLastSeen;
- int mLastTried;
-
- KnownNode(const char* ip,int port,int lastSeen,int lastTried);
-};
-
-class KnownNodeList
-{
- unsigned int mTriedIndex;
- std::vector mNodes;
-public:
- KnownNodeList();
-
- void load();
- void addNode();
- KnownNode* getNextNode();
-
-};
-
-#endif
\ No newline at end of file
diff --git a/src/NewcoinAddress.cpp b/src/NewcoinAddress.cpp
index 0ea477e6f..cbdea8105 100644
--- a/src/NewcoinAddress.cpp
+++ b/src/NewcoinAddress.cpp
@@ -10,13 +10,14 @@
#include
#include
#include
+#include
NewcoinAddress::NewcoinAddress()
{
nVersion = VER_NONE;
}
-bool NewcoinAddress::IsValid() const
+bool NewcoinAddress::isValid() const
{
return !vchData.empty();
}
@@ -26,8 +27,9 @@ void NewcoinAddress::clear()
nVersion = VER_NONE;
}
+#if 0
//
-// Hanko
+// Hanko - OBSOLETE
//
uint160 NewcoinAddress::getHanko() const
@@ -84,6 +86,7 @@ void NewcoinAddress::setHanko(const uint160& hash160)
void NewcoinAddress::setHanko(const NewcoinAddress& nodePublic) {
setHanko(nodePublic.getHanko());
}
+#endif
//
// NodePublic
diff --git a/src/NewcoinAddress.h b/src/NewcoinAddress.h
index b4bc8c248..6b696d093 100644
--- a/src/NewcoinAddress.h
+++ b/src/NewcoinAddress.h
@@ -27,11 +27,11 @@ private:
public:
NewcoinAddress();
- bool IsValid() const;
+ bool isValid() const;
void clear();
-
+#if 0
//
- // hanko
+ // hanko - OBSOLETE
//
uint160 getHanko() const;
@@ -40,7 +40,7 @@ public:
bool setHanko(const std::string& strHanko);
void setHanko(const uint160& hash160);
void setHanko(const NewcoinAddress& nodePublic);
-
+#endif
//
// Node Public
//
diff --git a/src/Peer.cpp b/src/Peer.cpp
index a5ae451eb..bf49ae0e3 100644
--- a/src/Peer.cpp
+++ b/src/Peer.cpp
@@ -1,23 +1,24 @@
#include
-#include
-//#include
#include
+#include
#include
#include
+//#include
#include "../json/writer.h"
#include "Peer.h"
-#include "KnownNodeList.h"
#include "Config.h"
#include "Application.h"
#include "Conversion.h"
#include "SerializedTransaction.h"
Peer::Peer(boost::asio::io_service& io_service)
- : mSocket(io_service)
+ : mSocket(io_service),
+ mCtx(boost::asio::ssl::context::sslv23),
+ mSocketSsl(io_service, mCtx)
{
}
@@ -53,22 +54,102 @@ void Peer::detach()
{
mSendQ.clear();
mSocket.close();
- if(!!mHanko) theApp->getConnectionPool().delFromMap(mHanko);
+
+ theApp->getConnectionPool().peerDisconnected(shared_from_this());
}
-void Peer::connected(const boost::system::error_code& error)
+// Begin trying to connect. We are not connected till we know and accept peer's public key.
+// Only takes IP addresses (not domains).
+void Peer::connect(const std::string strIp, int iPort)
{
- if(!error)
- {
- std::cout << "Connected to Peer." << std::endl; //BOOST_LOG_TRIVIAL(info) << "Connected to Peer.";
+ int iPortAct = iPort < 0 ? SYSTEM_PEER_PORT : iPort;
- sendHello();
- start_read_header();
+ boost::asio::ip::tcp::resolver::query query(strIp, boost::lexical_cast(iPortAct),
+ boost::asio::ip::resolver_query_base::numeric_host|boost::asio::ip::resolver_query_base::numeric_service);
+ boost::asio::ip::tcp::resolver resolver(theApp->getIOService());
+ boost::system::error_code err;
+ boost::asio::ip::tcp::resolver::iterator itrEndpoint = resolver.resolve(query, err);
+
+ if (err || itrEndpoint == boost::asio::ip::tcp::resolver::iterator())
+ {
+ // Failed to resolve ip.
+ detach();
}
else
{
+ mIpPort = make_pair(strIp, iPort);
+#if 1
+ boost::asio::async_connect(
+ mSocket,
+ itrEndpoint,
+ boost::bind(
+ &Peer::handleConnect,
+ shared_from_this(),
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::iterator));
+#else
+ // Connect via ssl.
+ // XXX Why doesn't handler need an iterator?
+ boost::asio::async_connect(
+ mSocketSsl.lowest_layer(),
+ itrEndpoint,
+ boost::bind(
+ &Peer::handleConnect,
+ shared_from_this(),
+ boost::asio::placeholders::error));
+#endif
+ }
+}
+
+// SSL connection.
+void Peer::handleConnect(const boost::system::error_code& error, boost::asio::ip::tcp::resolver::iterator it)
+{
+ if (error)
+ {
+ std::cout << "Socket Connect failed:" << error << std::endl;
detach();
- std::cout << "Peer::connected Error: " << error << std::endl; //else BOOST_LOG_TRIVIAL(info) << "Error: " << error;
+ }
+ else
+ {
+ std::cout << "Socket Connected." << std::endl;
+ // XXX Exchange public keys.
+ sendHello();
+ start_read_header();
+ }
+}
+
+// Peer connected via door.
+void Peer::connected(const boost::system::error_code& error)
+{
+ boost::asio::ip::tcp::endpoint ep = mSocket.remote_endpoint();
+ int iPort = ep.port();
+ std::string strIp = ep.address().to_string();
+
+ if (iPort == SYSTEM_PEER_PORT)
+ iPort = -1;
+
+ std::cout << "Remote peer: accept: " << strIp << " " << iPort << std::endl;
+
+ if (error)
+ {
+ std::cout << "Remote peer: accept error: " << error << std::endl;
+ detach();
+ }
+ else if (!theApp->getConnectionPool().peerAccepted(shared_from_this(), strIp, iPort))
+ {
+ std::cout << "Remote peer: rejecting." << std::endl;
+ // XXX Reject with a rejection message: already connected
+ detach();
+ }
+ else
+ {
+ std::cout << "Remote peer: accepted." << std::endl;
+ //BOOST_LOG_TRIVIAL(info) << "Connected to Peer.";
+
+ // Not redundant, add to connection list.
+ // XXX Exchange public keys.
+ sendHello();
+ start_read_header();
}
}
@@ -551,9 +632,9 @@ void Peer::punishPeer(PeerPunish)
Json::Value Peer::getJson() {
Json::Value ret(Json::objectValue);
- ret["ip"] = mSocket.remote_endpoint().address().to_string();
- ret["port"] = mSocket.remote_endpoint().port();
- ret["hanko"] = mHanko.ToString();
+ ret["ip"] = mSocket.remote_endpoint().address().to_string();
+ ret["port"] = mSocket.remote_endpoint().port();
+ ret["public_key"] = mPublicKey.ToString();
return ret;
}
diff --git a/src/Peer.h b/src/Peer.h
index 5ca7464e4..911755cce 100644
--- a/src/Peer.h
+++ b/src/Peer.h
@@ -2,9 +2,10 @@
#define __PEER__
#include
-#include
-#include
#include
+#include
+#include
+#include
#include "../obj/src/newcoin.pb.h"
#include "PackedMessage.h"
@@ -19,19 +20,30 @@ enum PeerPunish
PP_UNWANTED_DATA=3, // The peer sent us data we didn't want/need
};
+typedef std::pair ipPort;
+
class Peer : public boost::enable_shared_from_this
{
public:
static const int psbGotHello=0, psbSentHello=1, psbInMap=2, psbTrusted=3;
static const int psbNoLedgers=4, psbNoTransactions=5, psbDownLevel=6;
-protected:
+ NewcoinAddress mPublicKey; // Public key of peer.
+ ipPort mIpPort;
+
+ void handleConnect(const boost::system::error_code& error, boost::asio::ip::tcp::resolver::iterator it);
+
+private:
boost::asio::ip::tcp::socket mSocket;
+ boost::asio::ssl::context mCtx;
+ boost::asio::ssl::stream mSocketSsl;
+
+protected:
+
std::vector mReadbuf;
std::list mSendQ;
PackedMessage::pointer mSendingPacket;
std::bitset<32> mPeerBits;
- uint160 mHanko;
Peer(boost::asio::io_service& io_service);
@@ -42,7 +54,7 @@ protected:
void processReadBuffer();
void start_read_header();
void start_read_body(unsigned msg_len);
-
+
void sendPacketForce(PackedMessage::pointer packet);
void sendHello();
@@ -81,6 +93,7 @@ public:
return mSocket;
}
+ void connect(const std::string strIp, int iPort);
void connected(const boost::system::error_code& error);
void detach();
bool samePeer(Peer::pointer p) { return samePeer(*p); }
diff --git a/src/RPCServer.cpp b/src/RPCServer.cpp
index f9f970817..ea23907c3 100644
--- a/src/RPCServer.cpp
+++ b/src/RPCServer.cpp
@@ -205,12 +205,12 @@ Json::Value RPCServer::doCreateFamily(Json::Value& params)
family=theApp->getWallet().addFamily(query, false);
}
- if(!family.IsValid())
+ if(!family.isValid())
return JSONRPCError(500, "Invalid family specifier");
Json::Value ret(theApp->getWallet().getFamilyJson(family));
if(ret.isNull()) return JSONRPCError(500, "Invalid family");
- if(seed.IsValid())
+ if(seed.isValid())
{
ret["FamilySeed"]=seed.humanFamilySeed();
}
@@ -255,7 +255,7 @@ Json::Value RPCServer::doNewAccount(Json::Value ¶ms)
return JSONRPCError(500, "Family required");
NewcoinAddress family = parseFamily(fParam);
- if(!family.IsValid()) return JSONRPCError(500, "Family not found.");
+ if(!family.isValid()) return JSONRPCError(500, "Family not found.");
LocalAccount::pointer account(theApp->getWallet().getNewLocalAccount(family));
if(!account)
@@ -272,7 +272,7 @@ Json::Value RPCServer::doLock(Json::Value ¶ms)
if(extractString(fParam, params, 0))
{ // local
NewcoinAddress family = parseFamily(fParam);
- if(!family.IsValid()) return JSONRPCError(500, "Family not found");
+ if(!family.isValid()) return JSONRPCError(500, "Family not found");
theApp->getWallet().lock(family);
}
@@ -304,7 +304,7 @@ Json::Value RPCServer::doUnlock(Json::Value ¶ms)
// pass phrase
family=theApp->getWallet().addFamily(param, false);
- if(!family.IsValid())
+ if(!family.isValid())
return JSONRPCError(500, "Bad family");
Json::Value ret(theApp->getWallet().getFamilyJson(family));
@@ -339,7 +339,7 @@ Json::Value RPCServer::doFamilyInfo(Json::Value ¶ms)
extractString(fParam, params, 0);
NewcoinAddress family=parseFamily(fParam);
- if(!family.IsValid()) return JSONRPCError(500, "No such family");
+ if(!family.isValid()) return JSONRPCError(500, "No such family");
Json::Value obj(theApp->getWallet().getFamilyJson(family));
if(obj.isNull())
@@ -352,7 +352,7 @@ Json::Value RPCServer::doFamilyInfo(Json::Value ¶ms)
int kn=boost::lexical_cast(keyNum);
NewcoinAddress k=theApp->getWallet().peekKey(family, kn);
- if(k.IsValid())
+ if(k.isValid())
{
Json::Value key(Json::objectValue);
key["Number"]=kn;
@@ -367,14 +367,30 @@ Json::Value RPCServer::doFamilyInfo(Json::Value ¶ms)
Json::Value RPCServer::doConnect(Json::Value& params)
{
// connect [port]
- std::string host, port;
+ std::string strIp;
+ int iPort = -1;
- if(!extractString(host, params, 0))
- return JSONRPCError(500, "Host required");
- if(!extractString(port, params, 1))
- port="6561";
- if(!theApp->getConnectionPool().connectTo(host, port))
+ if(!params.isArray() || !params.size() || params.size() > 2)
+ return JSONRPCError(500, "Invalid parameters");
+
+ // XXX Might allow domain for manual connections.
+ if(!extractString(strIp, params, 0))
+ return JSONRPCError(500, "Host IP required");
+
+ if(params.size() == 2)
+ {
+ std::string strPort;
+
+ // YYY Should make an extract int.
+ if (!extractString(strPort, params, 1))
+ return JSONRPCError(500, "Bad port");
+
+ iPort = boost::lexical_cast(strPort);
+ }
+
+ if(!theApp->getConnectionPool().connectTo(strIp, iPort))
return JSONRPCError(500, "Unable to connect");
+
return "connecting";
}
@@ -400,7 +416,7 @@ Json::Value RPCServer::doSendTo(Json::Value& params)
return JSONRPCError(500, "Invalid parameters");
NewcoinAddress destAccount = parseAccount(sDest);
- if(!destAccount.IsValid())
+ if(!destAccount.isValid())
return JSONRPCError(500, "Unable to parse destination account");
uint64 iAmount;
@@ -713,7 +729,7 @@ Json::Value RPCServer::doCommand(const std::string& command, Json::Value& params
{
theApp->stop();
- return "newcoin server stopping";
+ return SYSTEM_NAME " server stopping";
}
if(command=="unl_add") return doUnlAdd(params);
diff --git a/src/UniqueNodeList.cpp b/src/UniqueNodeList.cpp
index 6a09339b3..afa17c2fa 100644
--- a/src/UniqueNodeList.cpp
+++ b/src/UniqueNodeList.cpp
@@ -1117,7 +1117,7 @@ void UniqueNodeList::setSeedDomains(const seedDomain& sdSource, bool bNext)
std::string strSql = str(boost::format("REPLACE INTO SeedDomains (Domain,PublicKey,Source,Next,Scan,Fetch,Sha256,Comment) VALUES (%s, %s, %s, %d, %d, %d, '%s', %s);")
% db->escape(sdSource.strDomain)
- % (sdSource.naPublicKey.IsValid() ? db->escape(sdSource.naPublicKey.humanNodePublic()) : "NULL")
+ % (sdSource.naPublicKey.isValid() ? db->escape(sdSource.naPublicKey.humanNodePublic()) : "NULL")
% db->escape(std::string(1, static_cast(sdSource.vsSource)))
% iNext
% iScan
diff --git a/src/UniqueNodeList.h b/src/UniqueNodeList.h
index 0b4b0ab99..83ea26ebc 100644
--- a/src/UniqueNodeList.h
+++ b/src/UniqueNodeList.h
@@ -6,15 +6,13 @@
#include "../json/value.h"
#include "NewcoinAddress.h"
-
+#include "Config.h"
#include "HttpsClient.h"
#include "ParseSection.h"
#include
#include
-#define SYSTEM_NAME "newcoin"
-
// Guarantees minimum thoughput of 1 node per second.
#define NODE_FETCH_JOBS 10
#define NODE_FETCH_SECONDS 10
diff --git a/src/Wallet.cpp b/src/Wallet.cpp
index 75056dad8..9353017f6 100644
--- a/src/Wallet.cpp
+++ b/src/Wallet.cpp
@@ -5,8 +5,9 @@
#include "openssl/ec.h"
#include
-#include
+#include
#include
+#include
#include
#include "Wallet.h"
@@ -347,32 +348,47 @@ Json::Value Wallet::getFamilyJson(const NewcoinAddress& family)
void Wallet::start()
{
+ // We need our node identity before we begin networking.
+ // - Allows others to identify if they have connected multiple times.
+ // - Determines our CAS routing and responsibilities.
+ // - This is not our validation identity.
+ if (!nodeIdentityLoad()) {
+ nodeIdentityCreate();
+ if (!nodeIdentityLoad())
+ throw std::runtime_error("unable to retrieve new node identity.");
+ }
+
+ std::cerr << "NodeIdentity: " << mNodePublicKey.humanNodePublic() << std::endl;
+
theApp->getUNL().start();
}
+// Retrieve network identity.
bool Wallet::nodeIdentityLoad()
{
- std::string strSql("SELECT * FROM NodeIdentity;");
-
Database* db=theApp->getWalletDB()->getDB();
ScopedLock sl(theApp->getWalletDB()->getDBLock());
+ bool bSuccess = false;
- if(!db->executeSQL(strSql.c_str())) return false;
- if(!db->startIterRows()) return false;
- std::string strPublicKey, strPrivateKey;
+ if(db->executeSQL("SELECT * FROM NodeIdentity;") && db->startIterRows())
+ {
+ std::string strPublicKey, strPrivateKey;
- db->getStr("PublicKey", strPublicKey);
- db->getStr("PrivateKey", strPrivateKey);
+ db->getStr("PublicKey", strPublicKey);
+ db->getStr("PrivateKey", strPrivateKey);
- mNodePublicKey.setNodePublic(strPublicKey);
- mNodePrivateKey.setNodePrivate(strPrivateKey);
+ mNodePublicKey.setNodePublic(strPublicKey);
+ mNodePrivateKey.setNodePrivate(strPrivateKey);
- db->endIterRows();
+ db->endIterRows();
+ bSuccess = true;
+ }
- return true;
+ return bSuccess;
}
+// Create and store a network identity.
bool Wallet::nodeIdentityCreate() {
//
// Generate the public and private key
@@ -389,48 +405,24 @@ bool Wallet::nodeIdentityCreate() {
nodePublicKey.setNodePublic(CKey(familyGenerator, 0).GetPubKey());
nodePrivateKey.setNodePrivate(CKey(familyGenerator, familySeed.getFamilyPrivateKey(), 0).GetSecret());
- std::cerr << "New NodeIdentity:" << std::endl;
- fprintf(stderr, "public: %s\n", nodePublicKey.humanNodePublic().c_str());
- fprintf(stderr, "private: %s\n", nodePrivateKey.humanNodePrivate().c_str());
+ std::cerr << "NodeIdentity: Created." << std::endl;
//
// Store the node information
//
Database* db = theApp->getWalletDB()->getDB();
- std::string strTmp;
-
- std::string strPublicKey = nodePublicKey.humanNodePublic();
- std::string strPrivateKey = nodePrivateKey.humanNodePrivate();
-
- std::string strSql = "INSERT INTO NodeIdentity (PublicKey,PrivateKey) VALUES (";
- db->escape(reinterpret_cast(strPublicKey.c_str()), strPublicKey.size(), strTmp);
- strSql.append(strTmp);
- strSql.append(",");
- db->escape(reinterpret_cast(strPrivateKey.c_str()), strPrivateKey.size(), strTmp);
- strSql.append(strTmp);
- strSql.append(");");
-
ScopedLock sl(theApp->getWalletDB()->getDBLock());
- db->executeSQL(strSql.c_str());
+ db->executeSQL(str(boost::format("INSERT INTO NodeIdentity (PublicKey,PrivateKey) VALUES (%s,%s);")
+ % db->escape(nodePublicKey.humanNodePublic())
+ % db->escape(nodePrivateKey.humanNodePrivate())));
+ // XXX Check error result.
return true;
}
void Wallet::load()
{
-#if 0
- // XXX Commented out because not currently used.
- if (!nodeIdentityLoad()) {
- nodeIdentityCreate();
- if (!nodeIdentityLoad())
- throw std::runtime_error("unable to retrieve new node identity.");
- }
-
- std::cerr << "NodeIdentity:" << std::endl;
- fprintf(stderr, "public: %s\n", mNodePublicKey.humanNodePublic().c_str());
- fprintf(stderr, "private: %s\n", mNodePrivateKey.humanNodePrivate().c_str());
-#endif
std::string sql("SELECT * FROM LocalAcctFamilies;");
ScopedLock sl(theApp->getWalletDB()->getDBLock());
@@ -569,7 +561,7 @@ LocalAccount::pointer Wallet::parseAccount(const std::string& specifier)
; // nothing
}
- return familyFound.IsValid()
+ return familyFound.isValid()
? getLocalAccount(familyFound, boost::lexical_cast(seq))
: LocalAccount::pointer();
}
diff --git a/src/base58.h b/src/base58.h
index f2603e6f6..53d13d704 100644
--- a/src/base58.h
+++ b/src/base58.h
@@ -18,6 +18,8 @@
#include
#include
#include
+#include
+#include
#include "bignum.h"
#include "BitcoinUtil.h"
@@ -241,7 +243,21 @@ public:
bool operator>=(const CBase58Data& b58) const { return CompareTo(b58) >= 0; }
bool operator< (const CBase58Data& b58) const { return CompareTo(b58) < 0; }
bool operator> (const CBase58Data& b58) const { return CompareTo(b58) > 0; }
+
+ friend std::size_t hash_value(CBase58Data const& b58);
};
+inline std::size_t hash_value(CBase58Data const& b58)
+{
+ std::size_t seed = 0;
+
+ boost::hash_combine(seed, b58.nVersion);
+ BOOST_FOREACH(const unsigned char& x, b58.vchData)
+ {
+ boost::hash_combine(seed, x);
+ }
+
+ return seed;
+}
#endif
// vim:ts=4
diff --git a/src/newcoin.proto b/src/newcoin.proto
index 6a66f6c6f..cb4eecbe0 100644
--- a/src/newcoin.proto
+++ b/src/newcoin.proto
@@ -225,3 +225,4 @@ message TMErrorMsg {
optional int32 errorCode = 1;
optional string message = 2;
}
+// vim:ts=4