Replace watchdogs with ping (#1491)
* Add hassentinelping to governanceinfo * sentinelping rpc call * additional fields in mnp * sentinel ping implementation * change sentinel state to byte in mnp * use adjusted time in sentinel ping * update nTimeLastWatchdogVote if sentinel ping is actual * remove unused fields * bump protocol to 70207 * Fix small issues - fix the error message text in CActivbeMasternodeUpdateSentinelPing; - add empty string before public: in CActiveMasternode class declaration; - rename field sentinelPing in CMasternodePing to sentinelIsActual and change $ - decrease sentinelVersion field size to uint16_t; * revert proto bump for MIN_... consts * revert changes in getgovernanceinfo * Update mn vote time for remote masternodes - call UpdateWatchdogVoteTime in CMasternodeMan::ProcessMessage - deserialize masternodeping from the previous version archive without exception - add ability to set time in UpdateWatchdogVoteTime - set nTimeLastWatchdogVote to masternode ping sigTime if sentinel is actual - bump CMasternodeMan::SERIALIZATION_VERSION_STRING * remove mn state checks and add correct rpc param convertion * fix var names * Helper class for version in string and integer form * String version in sentinel ping Version format is "x.x.x" * test for bacward compatibility in serialization * Change VersionInfo class to convert functions
This commit is contained in:
parent
f65017cfeb
commit
a439e98408
@ -108,6 +108,9 @@ bool CActiveMasternode::SendMasternodePing()
|
|||||||
}
|
}
|
||||||
|
|
||||||
CMasternodePing mnp(vin);
|
CMasternodePing mnp(vin);
|
||||||
|
mnp.nSentinelVersion = nSentinelVersion;
|
||||||
|
mnp.fSentinelIsCurrent =
|
||||||
|
(abs(GetAdjustedTime() - nSentinelPingTime) < MASTERNODE_WATCHDOG_MAX_SECONDS);
|
||||||
if(!mnp.Sign(keyMasternode, pubKeyMasternode)) {
|
if(!mnp.Sign(keyMasternode, pubKeyMasternode)) {
|
||||||
LogPrintf("CActiveMasternode::SendMasternodePing -- ERROR: Couldn't sign Masternode Ping\n");
|
LogPrintf("CActiveMasternode::SendMasternodePing -- ERROR: Couldn't sign Masternode Ping\n");
|
||||||
return false;
|
return false;
|
||||||
@ -127,6 +130,14 @@ bool CActiveMasternode::SendMasternodePing()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CActiveMasternode::UpdateSentinelPing(int version)
|
||||||
|
{
|
||||||
|
nSentinelVersion = version;
|
||||||
|
nSentinelPingTime = GetAdjustedTime();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void CActiveMasternode::ManageStateInitial()
|
void CActiveMasternode::ManageStateInitial()
|
||||||
{
|
{
|
||||||
LogPrint("masternode", "CActiveMasternode::ManageStateInitial -- status = %s, type = %s, pinger enabled = %d\n", GetStatus(), GetTypeString(), fPingerEnabled);
|
LogPrint("masternode", "CActiveMasternode::ManageStateInitial -- status = %s, type = %s, pinger enabled = %d\n", GetStatus(), GetTypeString(), fPingerEnabled);
|
||||||
|
@ -40,6 +40,10 @@ private:
|
|||||||
/// Ping Masternode
|
/// Ping Masternode
|
||||||
bool SendMasternodePing();
|
bool SendMasternodePing();
|
||||||
|
|
||||||
|
// sentinel ping data
|
||||||
|
int64_t nSentinelPingTime;
|
||||||
|
uint32_t nSentinelVersion;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Keys for the active Masternode
|
// Keys for the active Masternode
|
||||||
CPubKey pubKeyMasternode;
|
CPubKey pubKeyMasternode;
|
||||||
@ -52,6 +56,7 @@ public:
|
|||||||
int nState; // should be one of ACTIVE_MASTERNODE_XXXX
|
int nState; // should be one of ACTIVE_MASTERNODE_XXXX
|
||||||
std::string strNotCapableReason;
|
std::string strNotCapableReason;
|
||||||
|
|
||||||
|
|
||||||
CActiveMasternode()
|
CActiveMasternode()
|
||||||
: eType(MASTERNODE_UNKNOWN),
|
: eType(MASTERNODE_UNKNOWN),
|
||||||
fPingerEnabled(false),
|
fPingerEnabled(false),
|
||||||
@ -69,6 +74,8 @@ public:
|
|||||||
std::string GetStatus() const;
|
std::string GetStatus() const;
|
||||||
std::string GetTypeString() const;
|
std::string GetTypeString() const;
|
||||||
|
|
||||||
|
bool UpdateSentinelPing(int version);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ManageStateInitial();
|
void ManageStateInitial();
|
||||||
void ManageStateRemote();
|
void ManageStateRemote();
|
||||||
|
@ -735,7 +735,9 @@ void CMasternodeBroadcast::Relay()
|
|||||||
RelayInv(inv);
|
RelayInv(inv);
|
||||||
}
|
}
|
||||||
|
|
||||||
CMasternodePing::CMasternodePing(CTxIn& vinNew)
|
CMasternodePing::CMasternodePing(CTxIn& vinNew) :
|
||||||
|
fSentinelIsCurrent(false),
|
||||||
|
nSentinelVersion(0)
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
if (!chainActive.Tip() || chainActive.Height() < 12) return;
|
if (!chainActive.Tip() || chainActive.Height() < 12) return;
|
||||||
@ -751,6 +753,7 @@ bool CMasternodePing::Sign(CKey& keyMasternode, CPubKey& pubKeyMasternode)
|
|||||||
std::string strError;
|
std::string strError;
|
||||||
std::string strMasterNodeSignMessage;
|
std::string strMasterNodeSignMessage;
|
||||||
|
|
||||||
|
// TODO: add sentinel data
|
||||||
sigTime = GetAdjustedTime();
|
sigTime = GetAdjustedTime();
|
||||||
std::string strMessage = vin.ToString() + blockHash.ToString() + boost::lexical_cast<std::string>(sigTime);
|
std::string strMessage = vin.ToString() + blockHash.ToString() + boost::lexical_cast<std::string>(sigTime);
|
||||||
|
|
||||||
@ -769,6 +772,7 @@ bool CMasternodePing::Sign(CKey& keyMasternode, CPubKey& pubKeyMasternode)
|
|||||||
|
|
||||||
bool CMasternodePing::CheckSignature(CPubKey& pubKeyMasternode, int &nDos)
|
bool CMasternodePing::CheckSignature(CPubKey& pubKeyMasternode, int &nDos)
|
||||||
{
|
{
|
||||||
|
// TODO: add sentinel data
|
||||||
std::string strMessage = vin.ToString() + blockHash.ToString() + boost::lexical_cast<std::string>(sigTime);
|
std::string strMessage = vin.ToString() + blockHash.ToString() + boost::lexical_cast<std::string>(sigTime);
|
||||||
std::string strError = "";
|
std::string strError = "";
|
||||||
nDos = 0;
|
nDos = 0;
|
||||||
@ -909,10 +913,10 @@ void CMasternode::RemoveGovernanceObject(uint256 nGovernanceObjectHash)
|
|||||||
mapGovernanceObjectsVotedOn.erase(it);
|
mapGovernanceObjectsVotedOn.erase(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMasternode::UpdateWatchdogVoteTime()
|
void CMasternode::UpdateWatchdogVoteTime(uint64_t nVoteTime)
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(cs);
|
||||||
nTimeLastWatchdogVote = GetTime();
|
nTimeLastWatchdogVote = (nVoteTime == 0) ? GetTime() : nVoteTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -23,6 +23,7 @@ static const int MASTERNODE_WATCHDOG_MAX_SECONDS = 120 * 60;
|
|||||||
static const int MASTERNODE_NEW_START_REQUIRED_SECONDS = 180 * 60;
|
static const int MASTERNODE_NEW_START_REQUIRED_SECONDS = 180 * 60;
|
||||||
|
|
||||||
static const int MASTERNODE_POSE_BAN_MAX_SCORE = 5;
|
static const int MASTERNODE_POSE_BAN_MAX_SCORE = 5;
|
||||||
|
|
||||||
//
|
//
|
||||||
// The Masternode Ping Class : Contains a different serialize method for sending pings from masternodes throughout the network
|
// The Masternode Ping Class : Contains a different serialize method for sending pings from masternodes throughout the network
|
||||||
//
|
//
|
||||||
@ -34,13 +35,17 @@ public:
|
|||||||
uint256 blockHash;
|
uint256 blockHash;
|
||||||
int64_t sigTime; //mnb message times
|
int64_t sigTime; //mnb message times
|
||||||
std::vector<unsigned char> vchSig;
|
std::vector<unsigned char> vchSig;
|
||||||
|
bool fSentinelIsCurrent; // true if last sentinel ping was actual
|
||||||
|
uint32_t nSentinelVersion; // MSB is always 0, other 3 bits corresponds to x.x.x version scheme
|
||||||
//removed stop
|
//removed stop
|
||||||
|
|
||||||
CMasternodePing() :
|
CMasternodePing() :
|
||||||
vin(),
|
vin(),
|
||||||
blockHash(),
|
blockHash(),
|
||||||
sigTime(0),
|
sigTime(0),
|
||||||
vchSig()
|
vchSig(),
|
||||||
|
fSentinelIsCurrent(false),
|
||||||
|
nSentinelVersion(0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
CMasternodePing(CTxIn& vinNew);
|
CMasternodePing(CTxIn& vinNew);
|
||||||
@ -53,6 +58,10 @@ public:
|
|||||||
READWRITE(blockHash);
|
READWRITE(blockHash);
|
||||||
READWRITE(sigTime);
|
READWRITE(sigTime);
|
||||||
READWRITE(vchSig);
|
READWRITE(vchSig);
|
||||||
|
if(ser_action.ForRead() && (s.size() == 0))
|
||||||
|
return;
|
||||||
|
READWRITE(fSentinelIsCurrent);
|
||||||
|
READWRITE(nSentinelVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
void swap(CMasternodePing& first, CMasternodePing& second) // nothrow
|
void swap(CMasternodePing& first, CMasternodePing& second) // nothrow
|
||||||
@ -66,6 +75,8 @@ public:
|
|||||||
swap(first.blockHash, second.blockHash);
|
swap(first.blockHash, second.blockHash);
|
||||||
swap(first.sigTime, second.sigTime);
|
swap(first.sigTime, second.sigTime);
|
||||||
swap(first.vchSig, second.vchSig);
|
swap(first.vchSig, second.vchSig);
|
||||||
|
swap(first.fSentinelIsCurrent, second.fSentinelIsCurrent);
|
||||||
|
swap(first.nSentinelVersion, second.nSentinelVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint256 GetHash() const
|
uint256 GetHash() const
|
||||||
@ -318,7 +329,7 @@ public:
|
|||||||
|
|
||||||
void RemoveGovernanceObject(uint256 nGovernanceObjectHash);
|
void RemoveGovernanceObject(uint256 nGovernanceObjectHash);
|
||||||
|
|
||||||
void UpdateWatchdogVoteTime();
|
void UpdateWatchdogVoteTime(uint64_t nVoteTime = 0);
|
||||||
|
|
||||||
CMasternode& operator=(CMasternode from)
|
CMasternode& operator=(CMasternode from)
|
||||||
{
|
{
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
/** Masternode manager */
|
/** Masternode manager */
|
||||||
CMasternodeMan mnodeman;
|
CMasternodeMan mnodeman;
|
||||||
|
|
||||||
const std::string CMasternodeMan::SERIALIZATION_VERSION_STRING = "CMasternodeMan-Version-4";
|
const std::string CMasternodeMan::SERIALIZATION_VERSION_STRING = "CMasternodeMan-Version-5";
|
||||||
|
|
||||||
struct CompareLastPaidBlock
|
struct CompareLastPaidBlock
|
||||||
{
|
{
|
||||||
@ -849,6 +849,12 @@ void CMasternodeMan::ProcessMessage(CNode* pfrom, std::string& strCommand, CData
|
|||||||
// see if we have this Masternode
|
// see if we have this Masternode
|
||||||
CMasternode* pmn = mnodeman.Find(mnp.vin);
|
CMasternode* pmn = mnodeman.Find(mnp.vin);
|
||||||
|
|
||||||
|
// if masternode uses sentinel ping instead of watchdog
|
||||||
|
// we shoud update nTimeLastWatchdogVote here if sentinel
|
||||||
|
// ping flag is actual
|
||||||
|
if(pmn && mnp.fSentinelIsCurrent)
|
||||||
|
pmn->UpdateWatchdogVoteTime(mnp.sigTime);
|
||||||
|
|
||||||
// too late, new MNANNOUNCE is required
|
// too late, new MNANNOUNCE is required
|
||||||
if(pmn && pmn->IsNewStartRequired()) return;
|
if(pmn && pmn->IsNewStartRequired()) return;
|
||||||
|
|
||||||
@ -1642,6 +1648,11 @@ void CMasternodeMan::SetMasternodeLastPing(const CTxIn& vin, const CMasternodePi
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pMN->lastPing = mnp;
|
pMN->lastPing = mnp;
|
||||||
|
// if masternode uses sentinel ping instead of watchdog
|
||||||
|
// we shoud update nTimeLastWatchdogVote here if sentinel
|
||||||
|
// ping flag is actual
|
||||||
|
if(mnp.fSentinelIsCurrent)
|
||||||
|
pMN->UpdateWatchdogVoteTime(mnp.sigTime);
|
||||||
mapSeenMasternodePing.insert(std::make_pair(mnp.GetHash(), mnp));
|
mapSeenMasternodePing.insert(std::make_pair(mnp.GetHash(), mnp));
|
||||||
|
|
||||||
CMasternodeBroadcast mnb(*pMN);
|
CMasternodeBroadcast mnb(*pMN);
|
||||||
|
@ -972,3 +972,4 @@ UniValue getsuperblockbudget(const UniValue& params, bool fHelp)
|
|||||||
|
|
||||||
return strBudget;
|
return strBudget;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -795,3 +795,23 @@ UniValue masternodebroadcast(const UniValue& params, bool fHelp)
|
|||||||
|
|
||||||
return NullUniValue;
|
return NullUniValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UniValue sentinelping(const UniValue& params, bool fHelp)
|
||||||
|
{
|
||||||
|
if (fHelp || params.size() != 1) {
|
||||||
|
throw std::runtime_error(
|
||||||
|
"sentinelping version\n"
|
||||||
|
"\nSentinel ping.\n"
|
||||||
|
"\nArguments:\n"
|
||||||
|
"1. version (string, required) Sentinel version in the form \"x.x.x\"\n"
|
||||||
|
"\nResult:\n"
|
||||||
|
"state (boolean) Ping result\n"
|
||||||
|
"\nExamples:\n"
|
||||||
|
+ HelpExampleCli("sentinelping", "1.0.2")
|
||||||
|
+ HelpExampleRpc("sentinelping", "1.0.2")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
activeMasternode.UpdateSentinelPing(StringVersionToInt(params[0].get_str()));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
@ -353,6 +353,7 @@ static const CRPCCommand vRPCCommands[] =
|
|||||||
{ "dash", "mnsync", &mnsync, true },
|
{ "dash", "mnsync", &mnsync, true },
|
||||||
{ "dash", "spork", &spork, true },
|
{ "dash", "spork", &spork, true },
|
||||||
{ "dash", "getpoolinfo", &getpoolinfo, true },
|
{ "dash", "getpoolinfo", &getpoolinfo, true },
|
||||||
|
{ "dash", "sentinelping", &sentinelping, true },
|
||||||
#ifdef ENABLE_WALLET
|
#ifdef ENABLE_WALLET
|
||||||
{ "dash", "privatesend", &privatesend, false },
|
{ "dash", "privatesend", &privatesend, false },
|
||||||
|
|
||||||
|
@ -296,6 +296,7 @@ extern UniValue getchaintips(const UniValue& params, bool fHelp);
|
|||||||
extern UniValue invalidateblock(const UniValue& params, bool fHelp);
|
extern UniValue invalidateblock(const UniValue& params, bool fHelp);
|
||||||
extern UniValue reconsiderblock(const UniValue& params, bool fHelp);
|
extern UniValue reconsiderblock(const UniValue& params, bool fHelp);
|
||||||
extern UniValue getspentinfo(const UniValue& params, bool fHelp);
|
extern UniValue getspentinfo(const UniValue& params, bool fHelp);
|
||||||
|
extern UniValue sentinelping(const UniValue& params, bool fHelp);
|
||||||
|
|
||||||
bool StartRPC();
|
bool StartRPC();
|
||||||
void InterruptRPC();
|
void InterruptRPC();
|
||||||
|
@ -307,4 +307,11 @@ BOOST_AUTO_TEST_CASE(rpc_ban)
|
|||||||
BOOST_CHECK_EQUAL(adr.get_str(), "2001:4d48:ac57:400:cacf:e9ff:fe1d:9c63/128");
|
BOOST_CHECK_EQUAL(adr.get_str(), "2001:4d48:ac57:400:cacf:e9ff:fe1d:9c63/128");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(rpc_sentinel_ping)
|
||||||
|
{
|
||||||
|
BOOST_CHECK_NO_THROW(CallRPC("sentinelping 1.0.2"));
|
||||||
|
BOOST_CHECK_THROW(CallRPC("sentinelping"), runtime_error);
|
||||||
|
BOOST_CHECK_THROW(CallRPC("sentinelping 2"), bad_cast);
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
@ -276,4 +276,53 @@ BOOST_AUTO_TEST_CASE(insert_delete)
|
|||||||
BOOST_CHECK_EQUAL(ss.size(), 0);
|
BOOST_CHECK_EQUAL(ss.size(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Change struct size and check if it can be deserialized
|
||||||
|
// from old version archive and vice versa
|
||||||
|
struct old_version
|
||||||
|
{
|
||||||
|
int field1;
|
||||||
|
|
||||||
|
ADD_SERIALIZE_METHODS;
|
||||||
|
|
||||||
|
template <typename Stream, typename Operation>
|
||||||
|
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
||||||
|
READWRITE(field1);
|
||||||
|
}
|
||||||
|
};\
|
||||||
|
struct new_version
|
||||||
|
{
|
||||||
|
int field1;
|
||||||
|
int field2;
|
||||||
|
|
||||||
|
ADD_SERIALIZE_METHODS;
|
||||||
|
|
||||||
|
template <typename Stream, typename Operation>
|
||||||
|
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
||||||
|
READWRITE(field1);
|
||||||
|
if(ser_action.ForRead() && (s.size() == 0))
|
||||||
|
{
|
||||||
|
field2 = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
READWRITE(field2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(check_backward_compatibility)
|
||||||
|
{
|
||||||
|
CDataStream ss(SER_DISK, 0);
|
||||||
|
old_version old_src({5});
|
||||||
|
ss << old_src;
|
||||||
|
new_version new_dest({6, 7});
|
||||||
|
BOOST_REQUIRE_NO_THROW(ss >> new_dest);
|
||||||
|
BOOST_REQUIRE(old_src.field1 == new_dest.field1);
|
||||||
|
BOOST_REQUIRE(ss.size() == 0);
|
||||||
|
|
||||||
|
new_version new_src({6, 7});
|
||||||
|
ss << new_src;
|
||||||
|
old_version old_dest({5});
|
||||||
|
BOOST_REQUIRE_NO_THROW(ss >> old_dest);
|
||||||
|
BOOST_REQUIRE(new_src.field1 == old_dest.field1);
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
@ -489,4 +489,19 @@ BOOST_AUTO_TEST_CASE(test_ParseFixedPoint)
|
|||||||
BOOST_CHECK(!ParseFixedPoint("1.", 8, &amount));
|
BOOST_CHECK(!ParseFixedPoint("1.", 8, &amount));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(version_info_helper)
|
||||||
|
{
|
||||||
|
BOOST_CHECK(StringVersionToInt("1.1.1") == 0x010101);
|
||||||
|
BOOST_CHECK(IntVersionToString(0x010101) == "1.1.1");
|
||||||
|
|
||||||
|
BOOST_CHECK_THROW(StringVersionToInt("1.1.hgdghfgf"), bad_cast);
|
||||||
|
BOOST_CHECK_THROW(StringVersionToInt("1.1"), bad_cast);
|
||||||
|
BOOST_CHECK_THROW(StringVersionToInt("1.1.1f"), bad_cast);
|
||||||
|
BOOST_CHECK_THROW(StringVersionToInt("1.1.1000"), bad_cast);
|
||||||
|
BOOST_CHECK_THROW(StringVersionToInt("10"), bad_cast);
|
||||||
|
BOOST_CHECK_THROW(StringVersionToInt("1.1.1.1"), bad_cast);
|
||||||
|
BOOST_CHECK_THROW(IntVersionToString(0x01010101), bad_cast);
|
||||||
|
BOOST_CHECK_THROW(IntVersionToString(0), bad_cast);
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
38
src/util.cpp
38
src/util.cpp
@ -78,6 +78,8 @@
|
|||||||
#include <boost/algorithm/string/case_conv.hpp> // for to_lower()
|
#include <boost/algorithm/string/case_conv.hpp> // for to_lower()
|
||||||
#include <boost/algorithm/string/join.hpp>
|
#include <boost/algorithm/string/join.hpp>
|
||||||
#include <boost/algorithm/string/predicate.hpp> // for startswith() and endswith()
|
#include <boost/algorithm/string/predicate.hpp> // for startswith() and endswith()
|
||||||
|
#include <boost/algorithm/string/split.hpp>
|
||||||
|
#include <boost/algorithm/string/classification.hpp>
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
#include <boost/filesystem/fstream.hpp>
|
#include <boost/filesystem/fstream.hpp>
|
||||||
#include <boost/foreach.hpp>
|
#include <boost/foreach.hpp>
|
||||||
@ -952,3 +954,39 @@ int GetNumCores()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t StringVersionToInt(const std::string& strVersion)
|
||||||
|
{
|
||||||
|
std::vector<std::string> tokens;
|
||||||
|
boost::split(tokens, strVersion, boost::is_any_of("."));
|
||||||
|
if(tokens.size() != 3)
|
||||||
|
throw std::bad_cast();
|
||||||
|
uint32_t nVersion = 0;
|
||||||
|
for(unsigned idx = 0; idx < 3; idx++)
|
||||||
|
{
|
||||||
|
if(tokens[idx].length() == 0)
|
||||||
|
throw std::bad_cast();
|
||||||
|
uint32_t value = boost::lexical_cast<uint32_t>(tokens[idx]);
|
||||||
|
if(value > 255)
|
||||||
|
throw std::bad_cast();
|
||||||
|
nVersion <<= 8;
|
||||||
|
nVersion |= value;
|
||||||
|
}
|
||||||
|
return nVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string IntVersionToString(uint32_t nVersion)
|
||||||
|
{
|
||||||
|
if((nVersion >> 24) > 0) // MSB is always 0
|
||||||
|
throw std::bad_cast();
|
||||||
|
if(nVersion == 0)
|
||||||
|
throw std::bad_cast();
|
||||||
|
std::array<std::string, 3> tokens;
|
||||||
|
for(unsigned idx = 0; idx < 3; idx++)
|
||||||
|
{
|
||||||
|
unsigned shift = (2 - idx) * 8;
|
||||||
|
uint32_t byteValue = (nVersion >> shift) & 0xff;
|
||||||
|
tokens[idx] = boost::lexical_cast<std::string>(byteValue);
|
||||||
|
}
|
||||||
|
return boost::join(tokens, ".");
|
||||||
|
}
|
||||||
|
19
src/util.h
19
src/util.h
@ -271,4 +271,23 @@ template <typename Callable> void TraceThread(const char* name, Callable func)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Converts version strings to 4-byte unsigned integer
|
||||||
|
* @param strVersion version in "x.x.x" format (decimal digits only)
|
||||||
|
* @return 4-byte unsigned integer, most significant byte is always 0
|
||||||
|
* Throws std::bad_cast if format doesn\t match.
|
||||||
|
*/
|
||||||
|
uint32_t StringVersionToInt(const std::string& strVersion);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Converts version as 4-byte unsigned integer to string
|
||||||
|
* @param nVersion 4-byte unsigned integer, most significant byte is always 0
|
||||||
|
* @return version string in "x.x.x" format (last 3 bytes as version parts)
|
||||||
|
* Throws std::bad_cast if format doesn\t match.
|
||||||
|
*/
|
||||||
|
std::string IntVersionToString(uint32_t nVersion);
|
||||||
|
|
||||||
|
|
||||||
#endif // BITCOIN_UTIL_H
|
#endif // BITCOIN_UTIL_H
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
* network protocol versioning
|
* network protocol versioning
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static const int PROTOCOL_VERSION = 70206;
|
static const int PROTOCOL_VERSION = 70207;
|
||||||
|
|
||||||
//! initial proto version, to be increased after version/verack negotiation
|
//! initial proto version, to be increased after version/verack negotiation
|
||||||
static const int INIT_PROTO_VERSION = 209;
|
static const int INIT_PROTO_VERSION = 209;
|
||||||
|
Loading…
Reference in New Issue
Block a user