mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
Reformatting using AStyle
This commit is contained in:
@@ -10,490 +10,522 @@ class Features : public IFeatures
|
||||
{
|
||||
protected:
|
||||
|
||||
typedef boost::unordered_map<uint256, FeatureState> featureMap_t;
|
||||
typedef std::pair<const uint256, FeatureState> featureIt_t;
|
||||
typedef boost::unordered_set<uint256> featureList_t;
|
||||
typedef boost::unordered_map<uint256, FeatureState> featureMap_t;
|
||||
typedef std::pair<const uint256, FeatureState> featureIt_t;
|
||||
typedef boost::unordered_set<uint256> featureList_t;
|
||||
|
||||
boost::mutex mMutex;
|
||||
featureMap_t mFeatureMap;
|
||||
int mMajorityTime; // Seconds a feature must hold a majority
|
||||
int mMajorityFraction; // 256 = 100%
|
||||
uint32 mFirstReport; // close time of first majority report
|
||||
uint32 mLastReport; // close time of most recent majority report
|
||||
boost::mutex mMutex;
|
||||
featureMap_t mFeatureMap;
|
||||
int mMajorityTime; // Seconds a feature must hold a majority
|
||||
int mMajorityFraction; // 256 = 100%
|
||||
uint32 mFirstReport; // close time of first majority report
|
||||
uint32 mLastReport; // close time of most recent majority report
|
||||
|
||||
FeatureState* getCreateFeature(uint256 const& feature, bool create);
|
||||
bool shouldEnable (uint32 closeTime, const FeatureState& fs);
|
||||
void setJson(Json::Value& v, const FeatureState&);
|
||||
FeatureState* getCreateFeature (uint256 const& feature, bool create);
|
||||
bool shouldEnable (uint32 closeTime, const FeatureState& fs);
|
||||
void setJson (Json::Value& v, const FeatureState&);
|
||||
|
||||
public:
|
||||
|
||||
Features(uint32 majorityTime, int majorityFraction)
|
||||
: mMajorityTime(majorityTime), mMajorityFraction(majorityFraction), mFirstReport(0), mLastReport(0)
|
||||
{ ; }
|
||||
Features (uint32 majorityTime, int majorityFraction)
|
||||
: mMajorityTime (majorityTime), mMajorityFraction (majorityFraction), mFirstReport (0), mLastReport (0)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
void addInitialFeatures();
|
||||
void addInitialFeatures ();
|
||||
|
||||
FeatureState* addKnownFeature(const char *featureID, const char *friendlyName, bool veto);
|
||||
uint256 getFeature(const std::string& name);
|
||||
FeatureState* addKnownFeature (const char* featureID, const char* friendlyName, bool veto);
|
||||
uint256 getFeature (const std::string& name);
|
||||
|
||||
bool vetoFeature(uint256 const& feature);
|
||||
bool unVetoFeature(uint256 const& feature);
|
||||
bool vetoFeature (uint256 const& feature);
|
||||
bool unVetoFeature (uint256 const& feature);
|
||||
|
||||
bool enableFeature(uint256 const& feature);
|
||||
bool disableFeature(uint256 const& feature);
|
||||
bool enableFeature (uint256 const& feature);
|
||||
bool disableFeature (uint256 const& feature);
|
||||
|
||||
bool isFeatureEnabled(uint256 const& feature);
|
||||
bool isFeatureSupported(uint256 const& feature);
|
||||
bool isFeatureEnabled (uint256 const& feature);
|
||||
bool isFeatureSupported (uint256 const& feature);
|
||||
|
||||
void setEnabledFeatures(const std::vector<uint256>& features);
|
||||
void setSupportedFeatures(const std::vector<uint256>& features);
|
||||
void setEnabledFeatures (const std::vector<uint256>& features);
|
||||
void setSupportedFeatures (const std::vector<uint256>& features);
|
||||
|
||||
featureList_t getVetoedFeatures();
|
||||
featureList_t getEnabledFeatures();
|
||||
featureList_t getFeaturesToEnable(uint32 closeTime); // gets features we would vote to enable
|
||||
featureList_t getDesiredFeatures(); // features we support, do not veto, are not enabled
|
||||
featureList_t getVetoedFeatures ();
|
||||
featureList_t getEnabledFeatures ();
|
||||
featureList_t getFeaturesToEnable (uint32 closeTime); // gets features we would vote to enable
|
||||
featureList_t getDesiredFeatures (); // features we support, do not veto, are not enabled
|
||||
|
||||
void reportValidations(const FeatureSet&);
|
||||
void reportValidations (const FeatureSet&);
|
||||
|
||||
Json::Value getJson(int);
|
||||
Json::Value getJson(uint256 const& );
|
||||
Json::Value getJson (int);
|
||||
Json::Value getJson (uint256 const& );
|
||||
|
||||
void doValidation(Ledger::ref lastClosedLedger, STObject& baseValidation);
|
||||
void doVoting(Ledger::ref lastClosedLedger, SHAMap::ref initialPosition);
|
||||
void doValidation (Ledger::ref lastClosedLedger, STObject& baseValidation);
|
||||
void doVoting (Ledger::ref lastClosedLedger, SHAMap::ref initialPosition);
|
||||
};
|
||||
|
||||
void Features::addInitialFeatures()
|
||||
void Features::addInitialFeatures ()
|
||||
{
|
||||
// For each feature this version supports, construct the FeatureState object by calling
|
||||
// getCreateFeature. Set any vetoes or defaults. A pointer to the FeatureState can be stashed
|
||||
// For each feature this version supports, construct the FeatureState object by calling
|
||||
// getCreateFeature. Set any vetoes or defaults. A pointer to the FeatureState can be stashed
|
||||
|
||||
testFeature = addKnownFeature("1234", "testFeature", false);
|
||||
testFeature = addKnownFeature ("1234", "testFeature", false);
|
||||
}
|
||||
|
||||
FeatureState* Features::getCreateFeature(uint256 const& featureHash, bool create)
|
||||
{ // call with the mutex held
|
||||
featureMap_t::iterator it = mFeatureMap.find(featureHash);
|
||||
if (it == mFeatureMap.end())
|
||||
{
|
||||
if (!create)
|
||||
return NULL;
|
||||
FeatureState *feature = &(mFeatureMap[featureHash]);
|
||||
FeatureState* Features::getCreateFeature (uint256 const& featureHash, bool create)
|
||||
{
|
||||
// call with the mutex held
|
||||
featureMap_t::iterator it = mFeatureMap.find (featureHash);
|
||||
|
||||
{
|
||||
std::string query = "SELECT FirstMajority,LastMajority FROM Features WHERE hash='";
|
||||
query.append(featureHash.GetHex());
|
||||
query.append("';");
|
||||
if (it == mFeatureMap.end ())
|
||||
{
|
||||
if (!create)
|
||||
return NULL;
|
||||
|
||||
ScopedLock sl(theApp->getWalletDB()->getDBLock());
|
||||
Database* db = theApp->getWalletDB()->getDB();
|
||||
if (db->executeSQL(query) && db->startIterRows())
|
||||
{
|
||||
feature->mFirstMajority = db->getBigInt("FirstMajority");
|
||||
feature->mLastMajority = db->getBigInt("LastMajority");
|
||||
db->endIterRows();
|
||||
}
|
||||
}
|
||||
FeatureState* feature = & (mFeatureMap[featureHash]);
|
||||
|
||||
return feature;
|
||||
}
|
||||
return &(it->second);
|
||||
{
|
||||
std::string query = "SELECT FirstMajority,LastMajority FROM Features WHERE hash='";
|
||||
query.append (featureHash.GetHex ());
|
||||
query.append ("';");
|
||||
|
||||
ScopedLock sl (theApp->getWalletDB ()->getDBLock ());
|
||||
Database* db = theApp->getWalletDB ()->getDB ();
|
||||
|
||||
if (db->executeSQL (query) && db->startIterRows ())
|
||||
{
|
||||
feature->mFirstMajority = db->getBigInt ("FirstMajority");
|
||||
feature->mLastMajority = db->getBigInt ("LastMajority");
|
||||
db->endIterRows ();
|
||||
}
|
||||
}
|
||||
|
||||
return feature;
|
||||
}
|
||||
|
||||
return & (it->second);
|
||||
}
|
||||
|
||||
uint256 Features::getFeature(const std::string& name)
|
||||
uint256 Features::getFeature (const std::string& name)
|
||||
{
|
||||
if (!name.empty())
|
||||
{
|
||||
BOOST_FOREACH(featureMap_t::value_type& it, mFeatureMap)
|
||||
{
|
||||
if (name == it.second.mFriendlyName)
|
||||
return it.first;
|
||||
}
|
||||
}
|
||||
return uint256();
|
||||
if (!name.empty ())
|
||||
{
|
||||
BOOST_FOREACH (featureMap_t::value_type & it, mFeatureMap)
|
||||
{
|
||||
if (name == it.second.mFriendlyName)
|
||||
return it.first;
|
||||
}
|
||||
}
|
||||
|
||||
return uint256 ();
|
||||
}
|
||||
|
||||
FeatureState* Features::addKnownFeature(const char *featureID, const char *friendlyName, bool veto)
|
||||
FeatureState* Features::addKnownFeature (const char* featureID, const char* friendlyName, bool veto)
|
||||
{
|
||||
uint256 hash;
|
||||
hash.SetHex(featureID);
|
||||
if (hash.isZero())
|
||||
{
|
||||
assert(false);
|
||||
return NULL;
|
||||
}
|
||||
FeatureState* f = getCreateFeature(hash, true);
|
||||
uint256 hash;
|
||||
hash.SetHex (featureID);
|
||||
|
||||
if (friendlyName != NULL)
|
||||
f->setFriendlyName(friendlyName);
|
||||
if (hash.isZero ())
|
||||
{
|
||||
assert (false);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
f->mVetoed = veto;
|
||||
f->mSupported = true;
|
||||
FeatureState* f = getCreateFeature (hash, true);
|
||||
|
||||
return f;
|
||||
if (friendlyName != NULL)
|
||||
f->setFriendlyName (friendlyName);
|
||||
|
||||
f->mVetoed = veto;
|
||||
f->mSupported = true;
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
bool Features::vetoFeature(uint256 const& feature)
|
||||
bool Features::vetoFeature (uint256 const& feature)
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mMutex);
|
||||
FeatureState *s = getCreateFeature(feature, true);
|
||||
if (s->mVetoed)
|
||||
return false;
|
||||
s->mVetoed = true;
|
||||
return true;
|
||||
boost::mutex::scoped_lock sl (mMutex);
|
||||
FeatureState* s = getCreateFeature (feature, true);
|
||||
|
||||
if (s->mVetoed)
|
||||
return false;
|
||||
|
||||
s->mVetoed = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Features::unVetoFeature(uint256 const& feature)
|
||||
bool Features::unVetoFeature (uint256 const& feature)
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mMutex);
|
||||
FeatureState *s = getCreateFeature(feature, false);
|
||||
if (!s || !s->mVetoed)
|
||||
return false;
|
||||
s->mVetoed = false;
|
||||
return true;
|
||||
boost::mutex::scoped_lock sl (mMutex);
|
||||
FeatureState* s = getCreateFeature (feature, false);
|
||||
|
||||
if (!s || !s->mVetoed)
|
||||
return false;
|
||||
|
||||
s->mVetoed = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Features::enableFeature(uint256 const& feature)
|
||||
bool Features::enableFeature (uint256 const& feature)
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mMutex);
|
||||
FeatureState *s = getCreateFeature(feature, true);
|
||||
if (s->mEnabled)
|
||||
return false;
|
||||
s->mEnabled = true;
|
||||
return true;
|
||||
boost::mutex::scoped_lock sl (mMutex);
|
||||
FeatureState* s = getCreateFeature (feature, true);
|
||||
|
||||
if (s->mEnabled)
|
||||
return false;
|
||||
|
||||
s->mEnabled = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Features::disableFeature(uint256 const& feature)
|
||||
bool Features::disableFeature (uint256 const& feature)
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mMutex);
|
||||
FeatureState *s = getCreateFeature(feature, false);
|
||||
if (!s || !s->mEnabled)
|
||||
return false;
|
||||
s->mEnabled = false;
|
||||
return true;
|
||||
boost::mutex::scoped_lock sl (mMutex);
|
||||
FeatureState* s = getCreateFeature (feature, false);
|
||||
|
||||
if (!s || !s->mEnabled)
|
||||
return false;
|
||||
|
||||
s->mEnabled = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Features::isFeatureEnabled(uint256 const& feature)
|
||||
bool Features::isFeatureEnabled (uint256 const& feature)
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mMutex);
|
||||
FeatureState *s = getCreateFeature(feature, false);
|
||||
return s && s->mEnabled;
|
||||
boost::mutex::scoped_lock sl (mMutex);
|
||||
FeatureState* s = getCreateFeature (feature, false);
|
||||
return s && s->mEnabled;
|
||||
}
|
||||
|
||||
bool Features::isFeatureSupported(uint256 const& feature)
|
||||
bool Features::isFeatureSupported (uint256 const& feature)
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mMutex);
|
||||
FeatureState *s = getCreateFeature(feature, false);
|
||||
return s && s->mSupported;
|
||||
boost::mutex::scoped_lock sl (mMutex);
|
||||
FeatureState* s = getCreateFeature (feature, false);
|
||||
return s && s->mSupported;
|
||||
}
|
||||
|
||||
Features::featureList_t Features::getVetoedFeatures()
|
||||
Features::featureList_t Features::getVetoedFeatures ()
|
||||
{
|
||||
featureList_t ret;
|
||||
boost::mutex::scoped_lock sl(mMutex);
|
||||
BOOST_FOREACH(const featureIt_t& it, mFeatureMap)
|
||||
{
|
||||
if (it.second.mVetoed)
|
||||
ret.insert(it.first);
|
||||
}
|
||||
return ret;
|
||||
featureList_t ret;
|
||||
boost::mutex::scoped_lock sl (mMutex);
|
||||
BOOST_FOREACH (const featureIt_t & it, mFeatureMap)
|
||||
{
|
||||
if (it.second.mVetoed)
|
||||
ret.insert (it.first);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
Features::featureList_t Features::getEnabledFeatures()
|
||||
Features::featureList_t Features::getEnabledFeatures ()
|
||||
{
|
||||
featureList_t ret;
|
||||
boost::mutex::scoped_lock sl(mMutex);
|
||||
BOOST_FOREACH(const featureIt_t& it, mFeatureMap)
|
||||
{
|
||||
if (it.second.mEnabled)
|
||||
ret.insert(it.first);
|
||||
}
|
||||
return ret;
|
||||
featureList_t ret;
|
||||
boost::mutex::scoped_lock sl (mMutex);
|
||||
BOOST_FOREACH (const featureIt_t & it, mFeatureMap)
|
||||
{
|
||||
if (it.second.mEnabled)
|
||||
ret.insert (it.first);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Features::shouldEnable(uint32 closeTime, const FeatureState& fs)
|
||||
bool Features::shouldEnable (uint32 closeTime, const FeatureState& fs)
|
||||
{
|
||||
if (fs.mVetoed || fs.mEnabled || !fs.mSupported || (fs.mLastMajority != mLastReport))
|
||||
return false;
|
||||
if (fs.mVetoed || fs.mEnabled || !fs.mSupported || (fs.mLastMajority != mLastReport))
|
||||
return false;
|
||||
|
||||
if (fs.mFirstMajority == mFirstReport)
|
||||
{ // had a majority when we first started the server, relaxed check
|
||||
// WRITEME
|
||||
}
|
||||
// didn't have a majority when we first started the server, normal check
|
||||
return (fs.mLastMajority - fs.mFirstMajority) > mMajorityTime;
|
||||
if (fs.mFirstMajority == mFirstReport)
|
||||
{
|
||||
// had a majority when we first started the server, relaxed check
|
||||
// WRITEME
|
||||
}
|
||||
|
||||
// didn't have a majority when we first started the server, normal check
|
||||
return (fs.mLastMajority - fs.mFirstMajority) > mMajorityTime;
|
||||
|
||||
}
|
||||
|
||||
Features::featureList_t Features::getFeaturesToEnable(uint32 closeTime)
|
||||
Features::featureList_t Features::getFeaturesToEnable (uint32 closeTime)
|
||||
{
|
||||
featureList_t ret;
|
||||
boost::mutex::scoped_lock sl(mMutex);
|
||||
if (mLastReport != 0)
|
||||
{
|
||||
BOOST_FOREACH(const featureIt_t& it, mFeatureMap)
|
||||
{
|
||||
if (shouldEnable(closeTime, it.second))
|
||||
ret.insert(it.first);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
featureList_t ret;
|
||||
boost::mutex::scoped_lock sl (mMutex);
|
||||
|
||||
if (mLastReport != 0)
|
||||
{
|
||||
BOOST_FOREACH (const featureIt_t & it, mFeatureMap)
|
||||
{
|
||||
if (shouldEnable (closeTime, it.second))
|
||||
ret.insert (it.first);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Features::featureList_t Features::getDesiredFeatures()
|
||||
Features::featureList_t Features::getDesiredFeatures ()
|
||||
{
|
||||
featureList_t ret;
|
||||
boost::mutex::scoped_lock sl(mMutex);
|
||||
BOOST_FOREACH(const featureIt_t& it, mFeatureMap)
|
||||
{
|
||||
if (it.second.mSupported && !it.second.mEnabled && !it.second.mVetoed)
|
||||
ret.insert(it.first);
|
||||
}
|
||||
return ret;
|
||||
featureList_t ret;
|
||||
boost::mutex::scoped_lock sl (mMutex);
|
||||
BOOST_FOREACH (const featureIt_t & it, mFeatureMap)
|
||||
{
|
||||
if (it.second.mSupported && !it.second.mEnabled && !it.second.mVetoed)
|
||||
ret.insert (it.first);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Features::reportValidations(const FeatureSet& set)
|
||||
void Features::reportValidations (const FeatureSet& set)
|
||||
{
|
||||
if (set.mTrustedValidations == 0)
|
||||
return;
|
||||
int threshold = (set.mTrustedValidations * mMajorityFraction) / 256;
|
||||
if (set.mTrustedValidations == 0)
|
||||
return;
|
||||
|
||||
typedef std::map<uint256, int>::value_type u256_int_pair;
|
||||
int threshold = (set.mTrustedValidations * mMajorityFraction) / 256;
|
||||
|
||||
boost::mutex::scoped_lock sl(mMutex);
|
||||
typedef std::map<uint256, int>::value_type u256_int_pair;
|
||||
|
||||
if (mFirstReport == 0)
|
||||
mFirstReport = set.mCloseTime;
|
||||
boost::mutex::scoped_lock sl (mMutex);
|
||||
|
||||
std::vector<uint256> changedFeatures;
|
||||
changedFeatures.resize(set.mVotes.size());
|
||||
if (mFirstReport == 0)
|
||||
mFirstReport = set.mCloseTime;
|
||||
|
||||
BOOST_FOREACH(const u256_int_pair& it, set.mVotes)
|
||||
{
|
||||
FeatureState& state = mFeatureMap[it.first];
|
||||
WriteLog (lsDEBUG, Features) << "Feature " << it.first.GetHex() << " has " << it.second << " votes, needs " << threshold;
|
||||
if (it.second >= threshold)
|
||||
{ // we have a majority
|
||||
state.mLastMajority = set.mCloseTime;
|
||||
if (state.mFirstMajority == 0)
|
||||
{
|
||||
WriteLog (lsWARNING, Features) << "Feature " << it.first << " attains a majority vote";
|
||||
state.mFirstMajority = set.mCloseTime;
|
||||
changedFeatures.push_back(it.first);
|
||||
}
|
||||
}
|
||||
else // we have no majority
|
||||
{
|
||||
if (state.mFirstMajority != 0)
|
||||
{
|
||||
WriteLog (lsWARNING, Features) << "Feature " << it.first << " loses majority vote";
|
||||
state.mFirstMajority = 0;
|
||||
state.mLastMajority = 0;
|
||||
changedFeatures.push_back(it.first);
|
||||
}
|
||||
}
|
||||
}
|
||||
mLastReport = set.mCloseTime;
|
||||
std::vector<uint256> changedFeatures;
|
||||
changedFeatures.resize (set.mVotes.size ());
|
||||
|
||||
if (!changedFeatures.empty())
|
||||
{
|
||||
ScopedLock sl(theApp->getWalletDB()->getDBLock());
|
||||
Database* db = theApp->getWalletDB()->getDB();
|
||||
BOOST_FOREACH (const u256_int_pair & it, set.mVotes)
|
||||
{
|
||||
FeatureState& state = mFeatureMap[it.first];
|
||||
WriteLog (lsDEBUG, Features) << "Feature " << it.first.GetHex () << " has " << it.second << " votes, needs " << threshold;
|
||||
|
||||
db->executeSQL("BEGIN TRANSACTION;");
|
||||
BOOST_FOREACH(uint256 const& hash, changedFeatures)
|
||||
{
|
||||
FeatureState& fState = mFeatureMap[hash];
|
||||
db->executeSQL(boost::str(boost::format(
|
||||
"UPDATE Features SET FirstMajority = %d WHERE Hash = '%s';"
|
||||
) % fState.mFirstMajority % hash.GetHex()));
|
||||
db->executeSQL(boost::str(boost::format(
|
||||
"UPDATE Features SET LastMajority = %d WHERE Hash = '%s';"
|
||||
) % fState.mLastMajority % hash.GetHex()));
|
||||
}
|
||||
db->executeSQL("END TRANSACTION;");
|
||||
changedFeatures.clear();
|
||||
}
|
||||
if (it.second >= threshold)
|
||||
{
|
||||
// we have a majority
|
||||
state.mLastMajority = set.mCloseTime;
|
||||
|
||||
if (state.mFirstMajority == 0)
|
||||
{
|
||||
WriteLog (lsWARNING, Features) << "Feature " << it.first << " attains a majority vote";
|
||||
state.mFirstMajority = set.mCloseTime;
|
||||
changedFeatures.push_back (it.first);
|
||||
}
|
||||
}
|
||||
else // we have no majority
|
||||
{
|
||||
if (state.mFirstMajority != 0)
|
||||
{
|
||||
WriteLog (lsWARNING, Features) << "Feature " << it.first << " loses majority vote";
|
||||
state.mFirstMajority = 0;
|
||||
state.mLastMajority = 0;
|
||||
changedFeatures.push_back (it.first);
|
||||
}
|
||||
}
|
||||
}
|
||||
mLastReport = set.mCloseTime;
|
||||
|
||||
if (!changedFeatures.empty ())
|
||||
{
|
||||
ScopedLock sl (theApp->getWalletDB ()->getDBLock ());
|
||||
Database* db = theApp->getWalletDB ()->getDB ();
|
||||
|
||||
db->executeSQL ("BEGIN TRANSACTION;");
|
||||
BOOST_FOREACH (uint256 const & hash, changedFeatures)
|
||||
{
|
||||
FeatureState& fState = mFeatureMap[hash];
|
||||
db->executeSQL (boost::str (boost::format (
|
||||
"UPDATE Features SET FirstMajority = %d WHERE Hash = '%s';"
|
||||
) % fState.mFirstMajority % hash.GetHex ()));
|
||||
db->executeSQL (boost::str (boost::format (
|
||||
"UPDATE Features SET LastMajority = %d WHERE Hash = '%s';"
|
||||
) % fState.mLastMajority % hash.GetHex ()));
|
||||
}
|
||||
db->executeSQL ("END TRANSACTION;");
|
||||
changedFeatures.clear ();
|
||||
}
|
||||
}
|
||||
|
||||
void Features::setEnabledFeatures(const std::vector<uint256>& features)
|
||||
void Features::setEnabledFeatures (const std::vector<uint256>& features)
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mMutex);
|
||||
BOOST_FOREACH(featureIt_t& it, mFeatureMap)
|
||||
{
|
||||
it.second.mEnabled = false;
|
||||
}
|
||||
BOOST_FOREACH(uint256 const& it, features)
|
||||
{
|
||||
mFeatureMap[it].mEnabled = true;
|
||||
}
|
||||
boost::mutex::scoped_lock sl (mMutex);
|
||||
BOOST_FOREACH (featureIt_t & it, mFeatureMap)
|
||||
{
|
||||
it.second.mEnabled = false;
|
||||
}
|
||||
BOOST_FOREACH (uint256 const & it, features)
|
||||
{
|
||||
mFeatureMap[it].mEnabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Features::setSupportedFeatures(const std::vector<uint256>& features)
|
||||
void Features::setSupportedFeatures (const std::vector<uint256>& features)
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mMutex);
|
||||
BOOST_FOREACH(featureIt_t& it, mFeatureMap)
|
||||
{
|
||||
it.second.mSupported = false;
|
||||
}
|
||||
BOOST_FOREACH(uint256 const& it, features)
|
||||
{
|
||||
mFeatureMap[it].mSupported = true;
|
||||
}
|
||||
boost::mutex::scoped_lock sl (mMutex);
|
||||
BOOST_FOREACH (featureIt_t & it, mFeatureMap)
|
||||
{
|
||||
it.second.mSupported = false;
|
||||
}
|
||||
BOOST_FOREACH (uint256 const & it, features)
|
||||
{
|
||||
mFeatureMap[it].mSupported = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Features::doValidation(Ledger::ref lastClosedLedger, STObject& baseValidation)
|
||||
void Features::doValidation (Ledger::ref lastClosedLedger, STObject& baseValidation)
|
||||
{
|
||||
featureList_t lFeatures = getDesiredFeatures();
|
||||
if (lFeatures.empty())
|
||||
return;
|
||||
featureList_t lFeatures = getDesiredFeatures ();
|
||||
|
||||
STVector256 vFeatures(sfFeatures);
|
||||
BOOST_FOREACH(uint256 const& uFeature, lFeatures)
|
||||
{
|
||||
vFeatures.addValue(uFeature);
|
||||
}
|
||||
vFeatures.sort();
|
||||
baseValidation.setFieldV256(sfFeatures, vFeatures);
|
||||
if (lFeatures.empty ())
|
||||
return;
|
||||
|
||||
STVector256 vFeatures (sfFeatures);
|
||||
BOOST_FOREACH (uint256 const & uFeature, lFeatures)
|
||||
{
|
||||
vFeatures.addValue (uFeature);
|
||||
}
|
||||
vFeatures.sort ();
|
||||
baseValidation.setFieldV256 (sfFeatures, vFeatures);
|
||||
}
|
||||
|
||||
void Features::doVoting(Ledger::ref lastClosedLedger, SHAMap::ref initialPosition)
|
||||
void Features::doVoting (Ledger::ref lastClosedLedger, SHAMap::ref initialPosition)
|
||||
{
|
||||
featureList_t lFeatures = getFeaturesToEnable(lastClosedLedger->getCloseTimeNC());
|
||||
if (lFeatures.empty())
|
||||
return;
|
||||
featureList_t lFeatures = getFeaturesToEnable (lastClosedLedger->getCloseTimeNC ());
|
||||
|
||||
BOOST_FOREACH(uint256 const& uFeature, lFeatures)
|
||||
{
|
||||
WriteLog (lsWARNING, Features) << "Voting for feature: " << uFeature;
|
||||
SerializedTransaction trans(ttFEATURE);
|
||||
trans.setFieldAccount(sfAccount, uint160());
|
||||
trans.setFieldH256(sfFeature, uFeature);
|
||||
uint256 txID = trans.getTransactionID();
|
||||
WriteLog (lsWARNING, Features) << "Vote ID: " << txID;
|
||||
if (lFeatures.empty ())
|
||||
return;
|
||||
|
||||
Serializer s;
|
||||
trans.add(s, true);
|
||||
BOOST_FOREACH (uint256 const & uFeature, lFeatures)
|
||||
{
|
||||
WriteLog (lsWARNING, Features) << "Voting for feature: " << uFeature;
|
||||
SerializedTransaction trans (ttFEATURE);
|
||||
trans.setFieldAccount (sfAccount, uint160 ());
|
||||
trans.setFieldH256 (sfFeature, uFeature);
|
||||
uint256 txID = trans.getTransactionID ();
|
||||
WriteLog (lsWARNING, Features) << "Vote ID: " << txID;
|
||||
|
||||
SHAMapItem::pointer tItem = boost::make_shared<SHAMapItem>(txID, s.peekData());
|
||||
if (!initialPosition->addGiveItem(tItem, true, false))
|
||||
{
|
||||
WriteLog (lsWARNING, Features) << "Ledger already had feature transaction";
|
||||
}
|
||||
}
|
||||
Serializer s;
|
||||
trans.add (s, true);
|
||||
|
||||
SHAMapItem::pointer tItem = boost::make_shared<SHAMapItem> (txID, s.peekData ());
|
||||
|
||||
if (!initialPosition->addGiveItem (tItem, true, false))
|
||||
{
|
||||
WriteLog (lsWARNING, Features) << "Ledger already had feature transaction";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Json::Value Features::getJson(int)
|
||||
Json::Value Features::getJson (int)
|
||||
{
|
||||
Json::Value ret(Json::objectValue);
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mMutex);
|
||||
BOOST_FOREACH(const featureIt_t& it, mFeatureMap)
|
||||
{
|
||||
setJson(ret[it.first.GetHex()] = Json::objectValue, it.second);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
Json::Value ret (Json::objectValue);
|
||||
{
|
||||
boost::mutex::scoped_lock sl (mMutex);
|
||||
BOOST_FOREACH (const featureIt_t & it, mFeatureMap)
|
||||
{
|
||||
setJson (ret[it.first.GetHex ()] = Json::objectValue, it.second);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Features::setJson(Json::Value& v, const FeatureState& fs)
|
||||
void Features::setJson (Json::Value& v, const FeatureState& fs)
|
||||
{
|
||||
if (!fs.mFriendlyName.empty())
|
||||
v["name"] = fs.mFriendlyName;
|
||||
if (!fs.mFriendlyName.empty ())
|
||||
v["name"] = fs.mFriendlyName;
|
||||
|
||||
v["supported"] = fs.mSupported;
|
||||
v["vetoed"] = fs.mVetoed;
|
||||
v["supported"] = fs.mSupported;
|
||||
v["vetoed"] = fs.mVetoed;
|
||||
|
||||
if (fs.mEnabled)
|
||||
v["enabled"] = true;
|
||||
else
|
||||
{
|
||||
v["enabled"] = false;
|
||||
if (mLastReport != 0)
|
||||
{
|
||||
if (fs.mLastMajority == 0)
|
||||
{
|
||||
v["majority"] = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fs.mFirstMajority != 0)
|
||||
{
|
||||
if (fs.mFirstMajority == mFirstReport)
|
||||
v["majority_start"] = "start";
|
||||
else
|
||||
v["majority_start"] = fs.mFirstMajority;
|
||||
}
|
||||
if (fs.mLastMajority != 0)
|
||||
{
|
||||
if (fs.mLastMajority == mLastReport)
|
||||
v["majority_until"] = "now";
|
||||
else
|
||||
v["majority_until"] = fs.mLastMajority;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fs.mEnabled)
|
||||
v["enabled"] = true;
|
||||
else
|
||||
{
|
||||
v["enabled"] = false;
|
||||
|
||||
if (fs.mVetoed)
|
||||
v["veto"] = true;
|
||||
if (mLastReport != 0)
|
||||
{
|
||||
if (fs.mLastMajority == 0)
|
||||
{
|
||||
v["majority"] = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fs.mFirstMajority != 0)
|
||||
{
|
||||
if (fs.mFirstMajority == mFirstReport)
|
||||
v["majority_start"] = "start";
|
||||
else
|
||||
v["majority_start"] = fs.mFirstMajority;
|
||||
}
|
||||
|
||||
if (fs.mLastMajority != 0)
|
||||
{
|
||||
if (fs.mLastMajority == mLastReport)
|
||||
v["majority_until"] = "now";
|
||||
else
|
||||
v["majority_until"] = fs.mLastMajority;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fs.mVetoed)
|
||||
v["veto"] = true;
|
||||
}
|
||||
|
||||
Json::Value Features::getJson(uint256 const& feature)
|
||||
Json::Value Features::getJson (uint256 const& feature)
|
||||
{
|
||||
Json::Value ret = Json::objectValue;
|
||||
boost::mutex::scoped_lock sl(mMutex);
|
||||
setJson(ret[feature.GetHex()] = Json::objectValue, *getCreateFeature(feature, true));
|
||||
return ret;
|
||||
Json::Value ret = Json::objectValue;
|
||||
boost::mutex::scoped_lock sl (mMutex);
|
||||
setJson (ret[feature.GetHex ()] = Json::objectValue, *getCreateFeature (feature, true));
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<typename INT> class VotableInteger
|
||||
{
|
||||
protected:
|
||||
INT mCurrent; // The current setting
|
||||
INT mTarget; // The setting we want
|
||||
std::map<INT, int> mVoteMap;
|
||||
INT mCurrent; // The current setting
|
||||
INT mTarget; // The setting we want
|
||||
std::map<INT, int> mVoteMap;
|
||||
|
||||
public:
|
||||
VotableInteger(INT current, INT target) : mCurrent(current), mTarget(target)
|
||||
{
|
||||
++mVoteMap[mTarget]; // Add our vote
|
||||
}
|
||||
VotableInteger (INT current, INT target) : mCurrent (current), mTarget (target)
|
||||
{
|
||||
++mVoteMap[mTarget]; // Add our vote
|
||||
}
|
||||
|
||||
bool mayVote()
|
||||
{
|
||||
return mCurrent != mTarget; // If we love the current setting, we will not vote
|
||||
}
|
||||
bool mayVote ()
|
||||
{
|
||||
return mCurrent != mTarget; // If we love the current setting, we will not vote
|
||||
}
|
||||
|
||||
void addVote(INT vote)
|
||||
{
|
||||
++mVoteMap[vote];
|
||||
}
|
||||
void addVote (INT vote)
|
||||
{
|
||||
++mVoteMap[vote];
|
||||
}
|
||||
|
||||
void noVote()
|
||||
{
|
||||
addVote(mCurrent);
|
||||
}
|
||||
void noVote ()
|
||||
{
|
||||
addVote (mCurrent);
|
||||
}
|
||||
|
||||
INT getVotes()
|
||||
{
|
||||
INT ourVote = mCurrent;
|
||||
int weight = 0;
|
||||
INT getVotes ()
|
||||
{
|
||||
INT ourVote = mCurrent;
|
||||
int weight = 0;
|
||||
|
||||
typedef typename std::map<INT, int>::value_type mapVType;
|
||||
BOOST_FOREACH(const mapVType& value, mVoteMap)
|
||||
{ // Take most voted value between current and target, inclusive
|
||||
// FIXME: Should take best value that can get a significant majority
|
||||
if ((value.first <= std::max(mTarget, mCurrent)) &&
|
||||
(value.first >= std::min(mTarget, mCurrent)) &&
|
||||
(value.second > weight))
|
||||
{
|
||||
ourVote = value.first;
|
||||
weight = value.second;
|
||||
}
|
||||
}
|
||||
typedef typename std::map<INT, int>::value_type mapVType;
|
||||
BOOST_FOREACH (const mapVType & value, mVoteMap)
|
||||
{
|
||||
// Take most voted value between current and target, inclusive
|
||||
// FIXME: Should take best value that can get a significant majority
|
||||
if ((value.first <= std::max (mTarget, mCurrent)) &&
|
||||
(value.first >= std::min (mTarget, mCurrent)) &&
|
||||
(value.second > weight))
|
||||
{
|
||||
ourVote = value.first;
|
||||
weight = value.second;
|
||||
}
|
||||
}
|
||||
|
||||
return ourVote;
|
||||
}
|
||||
return ourVote;
|
||||
}
|
||||
};
|
||||
|
||||
IFeatures* IFeatures::New (uint32 majorityTime, int majorityFraction)
|
||||
|
||||
Reference in New Issue
Block a user