Merge branch 'bootstrap'

This commit is contained in:
Arthur Britto
2012-04-26 15:25:18 -07:00
22 changed files with 416 additions and 323 deletions

View File

@@ -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 = []

View File

@@ -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);

View File

@@ -1,3 +0,0 @@
<nodes>
<node ip="127.0.0.1" port="4000" last="0" />
</nodes>

View File

@@ -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<SerializedLedgerEntry>(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)

View File

@@ -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.

View File

@@ -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;

View File

@@ -6,7 +6,7 @@
#include <fstream>
#include <boost/lexical_cast.hpp>
#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;

View File

@@ -1,4 +1,11 @@
#include "string"
#ifndef __CONFIG__
#define __CONFIG__
#include <string>
#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

View File

@@ -1,32 +1,163 @@
#include <boost/foreach.hpp>
#include <boost/asio.hpp>
#include <boost/foreach.hpp>
#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; n<theConfig.NUMBER_CONNECTIONS; n++)
// XXX Start running policy.
}
// XXX Broken don't send a message to a peer if we got it from the peer.
void ConnectionPool::relayMessage(Peer* fromPeer, PackedMessage::pointer msg)
{
BOOST_FOREACH(naPeer pair, mConnectedMap)
{
KnownNode* node=nodeList.getNextNode();
if(!node) return;
Peer::pointer peer=Peer::create(io_service);
// peer->connectTo(*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<ipPort, Peer::pointer>::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<ipPort, Peer::pointer>::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<NewcoinAddress, Peer::pointer>::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<ipPort, Peer::pointer>::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; n<mBroadcastMessages.size(); n++)
@@ -35,89 +166,6 @@ bool ConnectionPool::isMessageKnown(PackedMessage::pointer msg)
}
return(false);
}
*/
#endif
void ConnectionPool::relayMessage(Peer* fromPeer, PackedMessage::pointer msg)
{
BOOST_FOREACH(Peer::pointer peer, mPeers)
{
if(!fromPeer || !(peer.get() == fromPeer))
peer->sendPacket(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<uint160, Peer::pointer>::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<uint160, Peer::pointer>::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<uint160, Peer::pointer> 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

View File

@@ -1,41 +1,65 @@
#ifndef __CONNECTION_POOL__
#define __CONNECTION_POOL__
#include <boost/asio.hpp>
#include <boost/thread/mutex.hpp>
#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<Peer::pointer> mPeers; // FIXME
std::map<uint160, Peer::pointer> peerMap;
//std::vector<std::pair<PackedMessage::pointer,int> > mBroadcastMessages;
private:
boost::mutex mPeerLock;
typedef std::pair<NewcoinAddress, Peer::pointer> 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<ipPort, Peer::pointer> mIpMap;
// Non-thin peers which we are connected to.
boost::unordered_map<NewcoinAddress, Peer::pointer> 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<uint160, Peer::pointer> 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<std::pair<PackedMessage::pointer,int> > mBroadcastMessages;
bool isMessageKnown(PackedMessage::pointer msg);
#endif
};
#endif

View File

@@ -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]));
}
}

View File

@@ -1,31 +0,0 @@
#ifndef __KNOWNNODELIST__
#define __KNOWNNODELIST__
#include "vector"
#include <string>
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 <KnownNode> mNodes;
public:
KnownNodeList();
void load();
void addNode();
KnownNode* getNextNode();
};
#endif

View File

@@ -10,13 +10,14 @@
#include <algorithm>
#include <iostream>
#include <boost/format.hpp>
#include <boost/functional/hash.hpp>
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

View File

@@ -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
//

View File

@@ -1,23 +1,24 @@
#include <iostream>
#include <boost/foreach.hpp>
//#include <boost/log/trivial.hpp>
#include <boost/bind.hpp>
#include <boost/foreach.hpp>
#include <boost/make_shared.hpp>
#include <boost/ref.hpp>
//#include <boost/log/trivial.hpp>
#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<std::string>(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;
}

View File

@@ -2,9 +2,10 @@
#define __PEER__
#include <bitset>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/shared_ptr.hpp>
#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<std::string,int> ipPort;
class Peer : public boost::enable_shared_from_this<Peer>
{
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<boost::asio::ip::tcp::socket> mSocketSsl;
protected:
std::vector<uint8_t> mReadbuf;
std::list<PackedMessage::pointer> 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); }

View File

@@ -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 &params)
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 &params)
if(extractString(fParam, params, 0))
{ // local <family>
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 &params)
// 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 &params)
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 &params)
int kn=boost::lexical_cast<int>(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 &params)
Json::Value RPCServer::doConnect(Json::Value& params)
{
// connect <ip> [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<int>(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);

View File

@@ -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<char>(sdSource.vsSource)))
% iNext
% iScan

View File

@@ -6,15 +6,13 @@
#include "../json/value.h"
#include "NewcoinAddress.h"
#include "Config.h"
#include "HttpsClient.h"
#include "ParseSection.h"
#include <boost/thread/mutex.hpp>
#include <boost/unordered_map.hpp>
#define SYSTEM_NAME "newcoin"
// Guarantees minimum thoughput of 1 node per second.
#define NODE_FETCH_JOBS 10
#define NODE_FETCH_SECONDS 10

View File

@@ -5,8 +5,9 @@
#include "openssl/ec.h"
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/format.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/make_shared.hpp>
#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<const unsigned char*>(strPublicKey.c_str()), strPublicKey.size(), strTmp);
strSql.append(strTmp);
strSql.append(",");
db->escape(reinterpret_cast<const unsigned char*>(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<int>(seq))
: LocalAccount::pointer();
}

View File

@@ -18,6 +18,8 @@
#include <string>
#include <algorithm>
#include <vector>
#include <boost/foreach.hpp>
#include <boost/functional/hash.hpp>
#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

View File

@@ -225,3 +225,4 @@ message TMErrorMsg {
optional int32 errorCode = 1;
optional string message = 2;
}
// vim:ts=4