From ef87efb96d0fb1ba46f7d85c4e2f2d69b4fdf942 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Sun, 24 Jun 2012 14:34:19 -0700 Subject: [PATCH 1/5] Explain how we're going to fix getLedgerByHash --- src/LedgerHistory.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/LedgerHistory.cpp b/src/LedgerHistory.cpp index 2d260c0ee0..8f9b1bec9e 100644 --- a/src/LedgerHistory.cpp +++ b/src/LedgerHistory.cpp @@ -63,6 +63,11 @@ Ledger::pointer LedgerHistory::getLedgerByHash(const uint256& hash) #if 0 // FIXME: A ledger without SHA maps isn't very useful // This code will need to build them + + // The fix is to audit all callers to this function and replace them with + // higher-level functions that ask more-specific questions that we can + // test against our database + ret = Ledger::loadByHash(hash); if (!ret) return ret; assert(ret->getHash() == hash); From 6018cba00ecb2a104180f43f6fc3b3d12e1571bd Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Sun, 24 Jun 2012 16:29:52 -0700 Subject: [PATCH 2/5] Track server and protocol version. --- src/Version.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/Version.h diff --git a/src/Version.h b/src/Version.h new file mode 100644 index 0000000000..1afd390afd --- /dev/null +++ b/src/Version.h @@ -0,0 +1,21 @@ + +// Versions + +#ifndef SERVER_VERSION_MAJ + +#define SERVER_VERSION_MAJ 0 +#define SERVER_VERSION_MIN 1 +#define SERVER_VERSION_SUB "-a" +#define SERVER_NAME "NewCoin" + +#define SV_STRINGIZE(x) #x +#define SERVER_VERSION \ + (SERVER_NAME "-" SV_STRINGIZE(SERVER_VERSION_MAJ) "." SV_STRINGIZE(SERVER_VERSION_MIN) SERVER_VERSION_SUB) + +#define PROTO_VERSION_MAJ 0 +#define PROTO_VERSION_MIN 0 + +#define MIN_PROTO_MAJ 0 +#define MIN_PROTO_MIN 0 + +#endif From 69d7b8a93d77435e0dc79f53f33339f39dbfee40 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Sun, 24 Jun 2012 16:30:13 -0700 Subject: [PATCH 3/5] Track server and protocol versions and minimum supported versions. This is a protocol-breaking change. It's needed because other protocol-breaking changes are needed for security reasons, and we don't want subtly-incompatible nodes connecting. --- src/Config.cpp | 2 -- src/Config.h | 4 ---- src/Peer.cpp | 34 ++++++++++++++++++++++++++-------- src/newcoin.proto | 22 ++++++++++++++-------- src/rpc.cpp | 7 ++----- 5 files changed, 42 insertions(+), 27 deletions(-) diff --git a/src/Config.cpp b/src/Config.cpp index 41030c187b..6e4b67ce87 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -112,8 +112,6 @@ void Config::setup(const std::string& strConf) // Defaults // - VERSION = 1; - NETWORK_START_TIME = 1319844908; PEER_PORT = SYSTEM_PEER_PORT; diff --git a/src/Config.h b/src/Config.h index f7a443b96d..6a88d13cfe 100644 --- a/src/Config.h +++ b/src/Config.h @@ -43,10 +43,6 @@ const int SYSTEM_WEBSOCKET_PORT = 6562; class Config { public: - // Core software parameters - int VERSION; - std::string VERSION_STR; - // Configuration parameters boost::filesystem::path CONFIG_FILE; boost::filesystem::path CONFIG_DIR; diff --git a/src/Peer.cpp b/src/Peer.cpp index f4cbbcb0a9..eb9ad2099e 100644 --- a/src/Peer.cpp +++ b/src/Peer.cpp @@ -8,6 +8,7 @@ #include "../json/writer.h" +#include "Version.h" #include "Peer.h" #include "Config.h" #include "Application.h" @@ -565,15 +566,20 @@ void Peer::processReadBuffer() void Peer::recvHello(newcoin::TMHello& packet) { -#ifdef DEBUG - Log(lsINFO) << "Recv(Hello) v=" << packet.version() << ", index=" << packet.ledgerindex(); -#endif + Log(lsTRACE) << "Recv(Hello) v=" << packet.versionmajor() << "." << packet.versionminor(); bool bDetach = true; // Cancel verification timeout. (void) mVerifyTimer.cancel(); - if (!mNodePublic.setNodePublic(packet.nodepublic())) + if ((packet.minprotoversionmajor() > PROTO_VERSION_MAJ) || + ((packet.minprotoversionmajor() == PROTO_VERSION_MAJ) && (packet.minprotoversionminor() > PROTO_VERSION_MIN))) + { + Log(lsINFO) << "Recv(Hello): Server requires protocol version " << + packet.minprotoversionmajor() << "." << packet.minprotoversionminor() << " we run " << + PROTO_VERSION_MAJ << "." << PROTO_VERSION_MIN; + } + else if (!mNodePublic.setNodePublic(packet.nodepublic())) { Log(lsINFO) << "Recv(Hello): Disconnect: Bad node public key."; } @@ -585,6 +591,14 @@ void Peer::recvHello(newcoin::TMHello& packet) { // Successful connection. Log(lsINFO) << "Recv(Hello): Connect: " << mNodePublic.humanNodePublic(); + if ( (packet.versionmajor() != SERVER_VERSION_MAJ) || (packet.versionminor() != SERVER_VERSION_MIN)) + { + if (packet.has_fullversion()) + Log(lsINFO) << " Peer is running version " << packet.fullversion(); + else + Log(lsINFO) << " Peer is running version " << packet.versionmajor() << "." << packet.versionminor(); + } + if (mClientConnect) { // If we connected due to scan, no longer need to scan. @@ -1104,16 +1118,20 @@ void Peer::sendHello() newcoin::TMHello h; - h.set_version(theConfig.VERSION); - h.set_ledgerindex(theApp->getOPs().getCurrentLedgerID()); + h.set_versionmajor(SERVER_VERSION_MAJ); + h.set_versionminor(SERVER_VERSION_MIN); + h.set_protoversionmajor(PROTO_VERSION_MAJ); + h.set_protoversionminor(PROTO_VERSION_MIN); + h.set_minprotoversionminor(MIN_PROTO_MAJ); + h.set_minprotoversionmajor(MIN_PROTO_MIN); + h.set_fullversion(SERVER_VERSION); h.set_nettime(theApp->getOPs().getNetworkTimeNC()); h.set_nodepublic(theApp->getWallet().getNodePublic().humanNodePublic()); h.set_nodeproof(&vchSig[0], vchSig.size()); h.set_ipv4port(theConfig.PEER_PORT); Ledger::pointer closedLedger = theApp->getMasterLedger().getClosedLedger(); - assert(closedLedger && closedLedger->isClosed()); - if (closedLedger->isClosed()) + if (closedLedger && closedLedger->isClosed()) { uint256 hash = closedLedger->getHash(); h.set_closedledger(hash.begin(), hash.GetSerializeSize()); diff --git a/src/newcoin.proto b/src/newcoin.proto index 1b4e30f556..99d9b591fb 100644 --- a/src/newcoin.proto +++ b/src/newcoin.proto @@ -37,14 +37,20 @@ enum MessageType { message TMHello { - required uint32 version = 1; - optional uint32 ledgerIndex = 2; - optional uint64 netTime = 3; - optional bytes nodePublic = 4; // node may opt to remain anonymous - optional bytes nodeProof = 5; - optional uint32 ipv4Port = 6; - optional bytes closedLedger = 7; // our last closed ledger - optional bytes previousLedger = 8; // the ledger before the last closed ledger + required uint32 versionMinor = 1; + required uint32 versionMajor = 2; + required uint32 protoVersionMinor = 3; + required uint32 protoVersionMajor = 4; + required uint32 minProtoVersionMinor = 5; + required uint32 minProtoVersionMajor = 6; + required bytes nodePublic = 7; + required bytes nodeProof = 8; + optional string fullVersion = 9; + optional uint64 netTime = 10; + optional uint32 ipv4Port = 11; + optional uint32 ledgerIndex = 12; + optional bytes closedLedger = 13; // our last closed ledger + optional bytes previousLedger = 14; // the ledger before the last closed ledger } diff --git a/src/rpc.cpp b/src/rpc.cpp index 77a414cc4b..2a289197de 100644 --- a/src/rpc.cpp +++ b/src/rpc.cpp @@ -15,14 +15,11 @@ #include "BitcoinUtil.h" #include "Config.h" #include "Log.h" +#include "Version.h" using namespace boost; using namespace boost::asio; - - - - Json::Value JSONRPCError(int code, const std::string& message) { Json::Value error(Json::objectValue); @@ -116,7 +113,7 @@ std::string HTTPReply(int nStatus, const std::string& strMsg) rfc1123Time().c_str(), access.c_str(), strMsg.size(), - theConfig.VERSION_STR.c_str(), + SERVER_VERSION, strMsg.c_str()); } From 808cec521e1ced3582d645fd8afb6c7ad8002af5 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Sun, 24 Jun 2012 16:46:45 -0700 Subject: [PATCH 4/5] It's crap like that that makes me dislike C++ sometimes. --- src/Version.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Version.h b/src/Version.h index 1afd390afd..e9fe8bc151 100644 --- a/src/Version.h +++ b/src/Version.h @@ -8,7 +8,8 @@ #define SERVER_VERSION_SUB "-a" #define SERVER_NAME "NewCoin" -#define SV_STRINGIZE(x) #x +#define SV_STRINGIZE(x) SV_STRINGIZE2(x) +#define SV_STRINGIZE2(x) #x #define SERVER_VERSION \ (SERVER_NAME "-" SV_STRINGIZE(SERVER_VERSION_MAJ) "." SV_STRINGIZE(SERVER_VERSION_MIN) SERVER_VERSION_SUB) From b4eea47a106a931ada40df3fbde3115f24e4fc40 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Sun, 24 Jun 2012 16:47:47 -0700 Subject: [PATCH 5/5] Track peer versions and put in the Json output. --- src/Peer.cpp | 26 +++++++++++++++++++------- src/Peer.h | 1 + 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/Peer.cpp b/src/Peer.cpp index eb9ad2099e..ea677631ca 100644 --- a/src/Peer.cpp +++ b/src/Peer.cpp @@ -590,6 +590,7 @@ void Peer::recvHello(newcoin::TMHello& packet) else { // Successful connection. Log(lsINFO) << "Recv(Hello): Connect: " << mNodePublic.humanNodePublic(); + mHello = packet; if ( (packet.versionmajor() != SERVER_VERSION_MAJ) || (packet.versionminor() != SERVER_VERSION_MIN)) { @@ -1159,13 +1160,24 @@ void Peer::punishPeer(PeerPunish) { } -Json::Value Peer::getJson() { - Json::Value ret(Json::objectValue); +Json::Value Peer::getJson() +{ + Json::Value ret(Json::objectValue); - ret["this"] = ADDRESS(this); - ret["public_key"] = mNodePublic.ToString(); - ret["ip"] = mIpPortConnect.first; - ret["port"] = mIpPortConnect.second; + ret["this"] = ADDRESS(this); + ret["public_key"] = mNodePublic.ToString(); + ret["ip"] = mIpPortConnect.first; + ret["port"] = mIpPortConnect.second; + + if (mHello.has_fullversion()) + ret["version"] = mHello.fullversion(); + else if (mHello.has_versionminor() && mHello.has_versionmajor()) + ret["version"] = boost::lexical_cast(mHello.versionmajor()) + "." + + boost::lexical_cast(mHello.versionminor()); + + if (mHello.has_protoversionminor() && mHello.has_protoversionmajor()) + ret["protocol"] = boost::lexical_cast(mHello.protoversionmajor()) + "." + + boost::lexical_cast(mHello.protoversionminor()); if (!mIpPort.first.empty()) { @@ -1173,7 +1185,7 @@ Json::Value Peer::getJson() { ret["verified_port"] = mIpPort.second; } - return ret; + return ret; } // vim:ts=4 diff --git a/src/Peer.h b/src/Peer.h index 3150532efa..3223632904 100644 --- a/src/Peer.h +++ b/src/Peer.h @@ -55,6 +55,7 @@ protected: std::list mSendQ; PackedMessage::pointer mSendingPacket; newcoin::TMStatusChange mLastStatus; + newcoin::TMHello mHello; Peer(boost::asio::io_service& io_service, boost::asio::ssl::context& ctx);