Rename Feature to Amendment:

* Added a README.md describing an Amendment
This commit is contained in:
Miguel Portilla
2014-04-29 18:32:06 -04:00
committed by Vinnie Falco
parent 98612a7cd6
commit 3025d8611b
25 changed files with 280 additions and 242 deletions

View File

@@ -1072,7 +1072,7 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple_app\misc\FeaturesImpl.cpp">
<ClCompile Include="..\..\src\ripple_app\misc\AmendmentTableImpl.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
@@ -2952,7 +2952,7 @@
<ClInclude Include="..\..\src\ripple_app\misc\AccountItems.h" />
<ClInclude Include="..\..\src\ripple_app\misc\AccountState.h" />
<ClInclude Include="..\..\src\ripple_app\misc\CanonicalTXSet.h" />
<ClInclude Include="..\..\src\ripple_app\misc\FeatureTable.h" />
<ClInclude Include="..\..\src\ripple_app\misc\AmendmentTable.h" />
<ClInclude Include="..\..\src\ripple_app\misc\FeeVote.h" />
<ClInclude Include="..\..\src\ripple_app\misc\IHashRouter.h" />
<ClInclude Include="..\..\src\ripple_app\misc\ProofOfWorkFactory.h" />
@@ -3247,6 +3247,7 @@
<None Include="..\..\src\ripple\validators\TODO.md" />
<None Include="..\..\src\ripple\validators\README.md" />
<None Include="..\..\src\ripple_app\ledger\TODO.md" />
<None Include="..\..\src\ripple_app\misc\README.md" />
<None Include="..\..\src\ripple_app\TODO.md" />
<None Include="..\..\src\ripple_core\nodestore\README.md" />
<None Include="..\..\src\ripple_overlay\README.md" />

View File

@@ -1716,10 +1716,10 @@
<ClCompile Include="..\..\src\ripple_rpc\impl\LookupLedger.cpp">
<Filter>[2] Old Ripple\ripple_rpc\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple_app\misc\FeaturesImpl.cpp">
<ClCompile Include="..\..\src\ripple_app\misc\FeeVoteImpl.cpp">
<Filter>[2] Old Ripple\ripple_app\misc</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple_app\misc\FeeVoteImpl.cpp">
<ClCompile Include="..\..\src\ripple_app\misc\AmendmentTableImpl.cpp">
<Filter>[2] Old Ripple\ripple_app\misc</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\proto\ripple.pb.cc">
@@ -3342,7 +3342,7 @@
<ClInclude Include="..\..\src\ripple_app\misc\FeeVote.h">
<Filter>[2] Old Ripple\ripple_app\misc</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple_app\misc\FeatureTable.h">
<ClInclude Include="..\..\src\ripple_app\misc\AmendmentTable.h">
<Filter>[2] Old Ripple\ripple_app\misc</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\proto\ripple.pb.h">
@@ -3473,8 +3473,9 @@
<None Include="..\..\src\ripple_core\nodestore\README.md">
<Filter>[2] Old Ripple\ripple_core\nodestore</Filter>
</None>
</ItemGroup>
<ItemGroup>
<None Include="..\..\src\ripple_app\misc\README.md">
<Filter>[2] Old Ripple\ripple_app\misc</Filter>
</None>
<CustomBuild Include="..\..\src\ripple\proto\ripple.proto">
<Filter>[1] Ripple\proto</Filter>
</CustomBuild>

View File

@@ -211,8 +211,8 @@ correctly to find the boost headers.
/** Config: RIPPLE_PROPOSE_FEATURES
This determines whether to add any features to the proposed transaction set.
*/
#ifndef RIPPLE_PROPOSE_FEATURES
#define RIPPLE_PROPOSE_FEATURES 0
#ifndef RIPPLE_PROPOSE_AMENDMENTS
#define RIPPLE_PROPOSE_AMENDMENTS 0
#endif
#endif

View File

@@ -961,7 +961,7 @@ private:
// next ledger is flag ledger
{
m_feeVote.doValidation (newLCL, *v);
getApp().getFeatureTable ().doValidation (newLCL, *v);
getApp().getAmendmentTable ().doValidation (newLCL, *v);
}
v->sign (signingHash, mValPrivate);
@@ -1491,7 +1491,7 @@ private:
SHAMap::pointer preSet
= initialLedger.peekTransactionMap ()->snapShot (true);
m_feeVote.doVoting (mPreviousLedger, preSet);
getApp().getFeatureTable ().doVoting (mPreviousLedger, preSet);
getApp().getAmendmentTable ().doVoting (mPreviousLedger, preSet);
initialSet = preSet->snapShot (false);
}
else

View File

@@ -1504,11 +1504,11 @@ uint256 Ledger::getLedgerFeeIndex ()
return s.getSHA512Half ();
}
uint256 Ledger::getLedgerFeatureIndex ()
uint256 Ledger::getLedgerAmendmentIndex ()
{
// get the index of the node that holds the enabled features
// get the index of the node that holds the enabled amendments
Serializer s (2);
s.add16 (spaceFeature);
s.add16 (spaceAmendment);
return s.getSHA512Half ();
}
@@ -1616,15 +1616,15 @@ std::vector< std::pair<std::uint32_t, uint256> > Ledger::getLedgerHashes ()
return ret;
}
std::vector<uint256> Ledger::getLedgerFeatures ()
std::vector<uint256> Ledger::getLedgerAmendments ()
{
std::vector<uint256> usFeatures;
SLE::pointer sleFeatures = getSLEi (getLedgerFeatureIndex ());
std::vector<uint256> usAmendments;
SLE::pointer sleAmendments = getSLEi (getLedgerAmendmentIndex ());
if (sleFeatures)
usFeatures = sleFeatures->getFieldV256 (sfFeatures).peekValue ();
if (sleAmendments)
usAmendments = sleAmendments->getFieldV256 (sfAmendments).peekValue ();
return usFeatures;
return usAmendments;
}
// XRP to XRP not allowed.

View File

@@ -300,9 +300,9 @@ public:
uint256 getLedgerHash (std::uint32_t ledgerIndex);
std::vector< std::pair<std::uint32_t, uint256> > getLedgerHashes ();
static uint256 getLedgerFeatureIndex ();
static uint256 getLedgerAmendmentIndex ();
static uint256 getLedgerFeeIndex ();
std::vector<uint256> getLedgerFeatures ();
std::vector<uint256> getLedgerAmendments ();
std::vector<uint256> getNeededTransactionHashes (int max, SHAMapSyncFilter * filter);
std::vector<uint256> getNeededAccountStateHashes (int max, SHAMapSyncFilter * filter);

View File

@@ -146,7 +146,7 @@ SOTemplate const& SerializedValidation::getFormat ()
format.push_back (SOElement (sfLedgerSequence, SOE_OPTIONAL));
format.push_back (SOElement (sfCloseTime, SOE_OPTIONAL));
format.push_back (SOElement (sfLoadFee, SOE_OPTIONAL));
format.push_back (SOElement (sfFeatures, SOE_OPTIONAL));
format.push_back (SOElement (sfAmendments, SOE_OPTIONAL));
format.push_back (SOElement (sfBaseFee, SOE_OPTIONAL));
format.push_back (SOElement (sfReserveBase, SOE_OPTIONAL));
format.push_back (SOElement (sfReserveIncrement, SOE_OPTIONAL));

View File

@@ -28,7 +28,7 @@ namespace ripple {
// VFALCO TODO Clean this global up
static bool volatile doShutdown = false;
static int const MAJORITY_FRACTION (200);
static int const MAJORITY_FRACTION (204);
//------------------------------------------------------------------------------
//
@@ -59,8 +59,8 @@ class PathRequestLog;
template <> char const* LogPartition::getPartitionName <PathRequestLog> () { return "PathRequest"; }
class RPCManagerLog;
template <> char const* LogPartition::getPartitionName <RPCManagerLog> () { return "RPCManager"; }
class FeaturesLog;
template <> char const* LogPartition::getPartitionName <FeaturesLog>() { return "FeatureTable"; }
class AmendmentTableLog;
template <> char const* LogPartition::getPartitionName <AmendmentTableLog>() { return "AmendmentTable"; }
template <> char const* LogPartition::getPartitionName <CollectorManager> () { return "Collector"; }
@@ -141,7 +141,7 @@ public:
std::unique_ptr <SNTPClient> m_sntpClient;
std::unique_ptr <TxQueue> m_txQueue;
std::unique_ptr <Validators::Manager> m_validators;
std::unique_ptr <FeatureTable> m_featureTable;
std::unique_ptr <AmendmentTable> m_amendmentTable;
std::unique_ptr <LoadFeeTrack> mFeeTrack;
std::unique_ptr <IHashRouter> mHashRouter;
std::unique_ptr <Validations> mValidations;
@@ -296,8 +296,8 @@ public:
getConfig ().getModuleDatabasePath (),
LogPartition::getJournal <ValidatorsLog> ())))
, m_featureTable (make_FeatureTable (weeks(2), MAJORITY_FRACTION, // 200/256
LogPartition::getJournal <FeaturesLog> ()))
, m_amendmentTable (make_AmendmentTable (weeks(2), MAJORITY_FRACTION, // 204/256 about 80%
LogPartition::getJournal <AmendmentTableLog> ()))
, mFeeTrack (LoadFeeTrack::New (LogPartition::getJournal <LoadManagerLog> ()))
@@ -450,9 +450,9 @@ public:
return *m_validators;
}
FeatureTable& getFeatureTable ()
AmendmentTable& getAmendmentTable()
{
return *m_featureTable;
return *m_amendmentTable;
}
LoadFeeTrack& getFeeTrack ()
@@ -609,7 +609,7 @@ public:
if (!getConfig ().RUN_STANDALONE)
updateTables ();
m_featureTable->addInitial ();
m_amendmentTable->addInitial();
Pathfinder::initPathTable ();
m_ledgerMaster->setMinValidations (getConfig ().VALIDATION_QUORUM);
@@ -1069,7 +1069,7 @@ void ApplicationImp::startNewLedger ()
{
Ledger::pointer firstLedger = boost::make_shared<Ledger> (rootAddress, SYSTEM_CURRENCY_START);
assert (!!firstLedger->getAccountState (rootAddress));
// WRITEME: Add any default features
// WRITEME: Add any default amendments
// WRITEME: Set default fee/reserve
firstLedger->updateHash ();
firstLedger->setClosed ();
@@ -1215,7 +1215,7 @@ bool serverOkay (std::string& reason)
return false;
}
if (getApp().getOPs ().isFeatureBlocked ())
if (getApp().getOPs ().isAmendmentBlocked ())
{
reason = "Server version too old";
return false;

View File

@@ -32,7 +32,7 @@ namespace RPC { class Manager; }
// VFALCO TODO Fix forward declares required for header dependency loops
class CollectorManager;
class FeatureTable;
class AmendmentTable;
class IHashRouter;
class LoadFeeTrack;
class Overlay;
@@ -88,7 +88,7 @@ public:
virtual NodeCache& getTempNodeCache () = 0;
virtual SLECache& getSLECache () = 0;
virtual Validators::Manager& getValidators () = 0;
virtual FeatureTable& getFeatureTable () = 0;
virtual AmendmentTable& getAmendmentTable() = 0;
virtual IHashRouter& getHashRouter () = 0;
virtual LoadFeeTrack& getFeeTrack () = 0;
virtual LoadManager& getLoadManager () = 0;

View File

@@ -17,22 +17,22 @@
*/
//==============================================================================
#ifndef RIPPLE_FEATURES_H
#define RIPPLE_FEATURES_H
#ifndef RIPPLE_AMENDMENT_TABLE_H
#define RIPPLE_AMENDMENT_TABLE_H
#include "../book/Types.h"
namespace ripple {
class FeatureSet
/** The status of all amendments requested in a given window. */
class AmendmentSet
{
// the status of all features requested in a given window
public:
std::uint32_t mCloseTime;
int mTrustedValidations; // number of trusted validations
ripple::unordered_map<uint256, int> mVotes; // yes votes by feature
ripple::unordered_map<uint256, int> mVotes; // yes votes by amendment
FeatureSet (std::uint32_t ct) : mCloseTime (ct), mTrustedValidations (0)
AmendmentSet (std::uint32_t ct) : mCloseTime (ct), mTrustedValidations (0)
{
;
}
@@ -40,16 +40,20 @@ public:
{
++mTrustedValidations;
}
void addVote (uint256 const& feature)
void addVote (uint256 const& amendment)
{
++mVotes[feature];
++mVotes[amendment];
}
};
class FeatureState
/** Current state of an amendment.
Tells if a amendment is supported, enabled or vetoed. A vetoed amendment
means the node will never announce its support.
*/
class AmendmentState
{
public:
bool mVetoed; // We don't want this feature enabled
bool mVetoed; // We don't want this amendment enabled
bool mEnabled;
bool mSupported;
bool mDefault; // Include in genesis ledger
@@ -59,7 +63,7 @@ public:
std::string mFriendlyName;
FeatureState ()
AmendmentState ()
: mVetoed (false), mEnabled (false), mSupported (false), mDefault (false),
m_firstMajority (0), m_lastMajority (0)
{
@@ -100,46 +104,44 @@ public:
}
};
/** Feature table interface.
The feature table stores the list of enabled and potential features.
Individuals features are voted on by validators during the consensus
/** The amendment table stores the list of enabled and potential amendments.
Individuals amendments are voted on by validators during the consensus
process.
*/
class FeatureTable
class AmendmentTable
{
public:
/** Create a new FeatureTable.
/** Create a new AmendmentTable.
@param majorityTime the number of seconds a feature must hold a majority
@param majorityTime the number of seconds an amendment must hold a majority
before we're willing to vote yes on it.
@param majorityFraction ratio, out of 256, of servers that must say
they want a feature before we consider it to
they want an amendment before we consider it to
have a majority.
@param journal
*/
virtual ~FeatureTable() { }
virtual ~AmendmentTable() { }
virtual void addInitial () = 0;
virtual FeatureState* addKnown (const char* featureID,
virtual AmendmentState* addKnown (const char* amendmentID,
const char* friendlyName, bool veto) = 0;
virtual uint256 get (const std::string& name) = 0;
virtual bool veto (uint256 const& feature) = 0;
virtual bool unVeto (uint256 const& feature) = 0;
virtual bool veto (uint256 const& amendment) = 0;
virtual bool unVeto (uint256 const& amendment) = 0;
virtual bool enable (uint256 const& feature) = 0;
virtual bool disable (uint256 const& feature) = 0;
virtual bool enable (uint256 const& amendment) = 0;
virtual bool disable (uint256 const& amendment) = 0;
virtual bool isEnabled (uint256 const& feature) = 0;
virtual bool isSupported (uint256 const& feature) = 0;
virtual bool isEnabled (uint256 const& amendment) = 0;
virtual bool isSupported (uint256 const& amendment) = 0;
virtual void setEnabled (const std::vector<uint256>& features) = 0;
virtual void setSupported (const std::vector<uint256>& features) = 0;
virtual void setEnabled (const std::vector<uint256>& amendments) = 0;
virtual void setSupported (const std::vector<uint256>& amendments) = 0;
virtual void reportValidations (const FeatureSet&) = 0;
virtual void reportValidations (const AmendmentSet&) = 0;
virtual Json::Value getJson (int) = 0;
virtual Json::Value getJson (uint256 const& ) = 0;
@@ -150,8 +152,8 @@ public:
doVoting (Ledger::ref lastClosedLedger, SHAMap::ref initialPosition) = 0;
};
std::unique_ptr<FeatureTable>
make_FeatureTable (std::chrono::seconds majorityTime, int majorityFraction,
std::unique_ptr<AmendmentTable>
make_AmendmentTable (std::chrono::seconds majorityTime, int majorityFraction,
beast::Journal journal);
} // ripple

View File

@@ -19,38 +19,38 @@
namespace ripple {
/** Track the list of "features"
/** Track the list of "amendments"
A "feature" is an option that can affect transaction processing
rules that is identified by a 256-bit feature identifier
An "amendment" is an option that can affect transaction processing
rules that is identified by a 256-bit amendment identifier
and adopted, or rejected, by the network.
*/
class FeaturesImpl : public FeatureTable
class AmendmentTableImpl : public AmendmentTable
{
protected:
typedef ripple::unordered_map<uint256, FeatureState> featureMap_t;
typedef std::pair<const uint256, FeatureState> featureIt_t;
typedef boost::unordered_set<uint256> featureList_t;
typedef ripple::unordered_map<uint256, AmendmentState> amendmentMap_t;
typedef std::pair<const uint256, AmendmentState> amendmentIt_t;
typedef boost::unordered_set<uint256> amendmentList_t;
typedef RippleMutex LockType;
typedef std::lock_guard <LockType> ScopedLockType;
LockType mLock;
featureMap_t mFeatureMap;
std::chrono::seconds m_majorityTime; // Seconds a feature must hold a majority
amendmentMap_t m_amendmentMap;
std::chrono::seconds m_majorityTime; // Seconds an amendment must hold a majority
int mMajorityFraction; // 256 = 100%
core::Clock::time_point m_firstReport; // close time of first majority report
core::Clock::time_point m_lastReport; // close time of most recent majority report
beast::Journal m_journal;
FeatureState* getCreate (uint256 const& feature, bool create);
bool shouldEnable (std::uint32_t closeTime, const FeatureState& fs);
void setJson (Json::Value& v, const FeatureState&);
AmendmentState* getCreate (uint256 const& amendment, bool create);
bool shouldEnable (std::uint32_t closeTime, const AmendmentState& fs);
void setJson (Json::Value& v, const AmendmentState&);
public:
FeaturesImpl (std::chrono::seconds majorityTime, int majorityFraction,
AmendmentTableImpl (std::chrono::seconds majorityTime, int majorityFraction,
beast::Journal journal)
: m_majorityTime (majorityTime)
, mMajorityFraction (majorityFraction)
@@ -62,23 +62,23 @@ public:
void addInitial () override;
FeatureState* addKnown (const char* featureID, const char* friendlyName,
AmendmentState* addKnown (const char* amendmentID, const char* friendlyName,
bool veto) override;
uint256 get (const std::string& name) override;
bool veto (uint256 const& feature) override;
bool unVeto (uint256 const& feature) override;
bool veto (uint256 const& amendment) override;
bool unVeto (uint256 const& amendment) override;
bool enable (uint256 const& feature) override;
bool disable (uint256 const& feature) override;
bool enable (uint256 const& amendment) override;
bool disable (uint256 const& amendment) override;
bool isEnabled (uint256 const& feature) override;
bool isSupported (uint256 const& feature) override;
bool isEnabled (uint256 const& amendment) override;
bool isSupported (uint256 const& amendment) override;
void setEnabled (const std::vector<uint256>& features) override;
void setSupported (const std::vector<uint256>& features) override;
void setEnabled (const std::vector<uint256>& amendments) override;
void setSupported (const std::vector<uint256>& amendments) override;
void reportValidations (const FeatureSet&) override;
void reportValidations (const AmendmentSet&) override;
Json::Value getJson (int) override;
Json::Value getJson (uint256 const&) override;
@@ -86,35 +86,35 @@ public:
void doValidation (Ledger::ref lastClosedLedger, STObject& baseValidation) override;
void doVoting (Ledger::ref lastClosedLedger, SHAMap::ref initialPosition) override;
featureList_t getVetoed ();
featureList_t getEnabled ();
featureList_t getToEnable (core::Clock::time_point closeTime); // gets features we would vote to enable
featureList_t getDesired (); // features we support, do not veto, are not enabled
amendmentList_t getVetoed();
amendmentList_t getEnabled();
amendmentList_t getToEnable(core::Clock::time_point closeTime); // gets amendments we would vote to enable
amendmentList_t getDesired(); // amendments we support, do not veto, are not enabled
};
void
FeaturesImpl::addInitial ()
AmendmentTableImpl::addInitial ()
{
// For each feature this version supports, construct the FeatureState object by calling
// addKnown. Set any vetoes or defaults. A pointer to the FeatureState can be stashed
// For each amendment this version supports, construct the AmendmentState object by calling
// addKnown. Set any vetoes or defaults. A pointer to the AmendmentState can be stashed
}
FeatureState*
FeaturesImpl::getCreate (uint256 const& featureHash, bool create)
AmendmentState*
AmendmentTableImpl::getCreate (uint256 const& amendmentHash, bool create)
{
// call with the mutex held
auto iter (mFeatureMap.find (featureHash));
auto iter (m_amendmentMap.find (amendmentHash));
if (iter == mFeatureMap.end ())
if (iter == m_amendmentMap.end())
{
if (!create)
return nullptr;
FeatureState* feature = & (mFeatureMap[featureHash]);
AmendmentState* amendment = & (m_amendmentMap[amendmentHash]);
{
std::string query = "SELECT FirstMajority,LastMajority FROM Features WHERE hash='";
query.append (featureHash.GetHex ());
query.append (amendmentHash.GetHex ());
query.append ("';");
DeprecatedScopedLock sl (getApp().getWalletDB ()->getDBLock ());
@@ -122,22 +122,22 @@ FeaturesImpl::getCreate (uint256 const& featureHash, bool create)
if (db->executeSQL (query) && db->startIterRows ())
{
feature->m_firstMajority = db->getBigInt("FirstMajority");
feature->m_lastMajority = db->getBigInt("LastMajority");
amendment->m_firstMajority = db->getBigInt("FirstMajority");
amendment->m_lastMajority = db->getBigInt("LastMajority");
db->endIterRows ();
}
}
return feature;
return amendment;
}
return & (iter->second);
}
uint256
FeaturesImpl::get (const std::string& name)
AmendmentTableImpl::get (const std::string& name)
{
for (auto const& e : mFeatureMap)
for (auto const& e : m_amendmentMap)
{
if (name == e.second.mFriendlyName)
return e.first;
@@ -146,12 +146,12 @@ FeaturesImpl::get (const std::string& name)
return uint256 ();
}
FeatureState*
FeaturesImpl::addKnown (const char* featureID, const char* friendlyName,
AmendmentState*
AmendmentTableImpl::addKnown (const char* amendmentID, const char* friendlyName,
bool veto)
{
uint256 hash;
hash.SetHex (featureID);
hash.SetHex (amendmentID);
if (hash.isZero ())
{
@@ -159,7 +159,7 @@ FeaturesImpl::addKnown (const char* featureID, const char* friendlyName,
return nullptr;
}
FeatureState* f = getCreate (hash, true);
AmendmentState* f = getCreate (hash, true);
if (friendlyName != nullptr)
f->setFriendlyName (friendlyName);
@@ -171,10 +171,10 @@ FeaturesImpl::addKnown (const char* featureID, const char* friendlyName,
}
bool
FeaturesImpl::veto (uint256 const& feature)
AmendmentTableImpl::veto (uint256 const& amendment)
{
ScopedLockType sl (mLock);
FeatureState* s = getCreate (feature, true);
AmendmentState* s = getCreate (amendment, true);
if (s->mVetoed)
return false;
@@ -184,10 +184,10 @@ FeaturesImpl::veto (uint256 const& feature)
}
bool
FeaturesImpl::unVeto (uint256 const& feature)
AmendmentTableImpl::unVeto (uint256 const& amendment)
{
ScopedLockType sl (mLock);
FeatureState* s = getCreate (feature, false);
AmendmentState* s = getCreate (amendment, false);
if (!s || !s->mVetoed)
return false;
@@ -197,10 +197,10 @@ FeaturesImpl::unVeto (uint256 const& feature)
}
bool
FeaturesImpl::enable (uint256 const& feature)
AmendmentTableImpl::enable (uint256 const& amendment)
{
ScopedLockType sl (mLock);
FeatureState* s = getCreate (feature, true);
AmendmentState* s = getCreate (amendment, true);
if (s->mEnabled)
return false;
@@ -210,10 +210,10 @@ FeaturesImpl::enable (uint256 const& feature)
}
bool
FeaturesImpl::disable (uint256 const& feature)
AmendmentTableImpl::disable (uint256 const& amendment)
{
ScopedLockType sl (mLock);
FeatureState* s = getCreate (feature, false);
AmendmentState* s = getCreate (amendment, false);
if (!s || !s->mEnabled)
return false;
@@ -223,27 +223,27 @@ FeaturesImpl::disable (uint256 const& feature)
}
bool
FeaturesImpl::isEnabled (uint256 const& feature)
AmendmentTableImpl::isEnabled (uint256 const& amendment)
{
ScopedLockType sl (mLock);
FeatureState* s = getCreate (feature, false);
AmendmentState* s = getCreate (amendment, false);
return s && s->mEnabled;
}
bool
FeaturesImpl::isSupported (uint256 const& feature)
AmendmentTableImpl::isSupported (uint256 const& amendment)
{
ScopedLockType sl (mLock);
FeatureState* s = getCreate (feature, false);
AmendmentState* s = getCreate (amendment, false);
return s && s->mSupported;
}
FeaturesImpl::featureList_t
FeaturesImpl::getVetoed ()
AmendmentTableImpl::amendmentList_t
AmendmentTableImpl::getVetoed ()
{
featureList_t ret;
amendmentList_t ret;
ScopedLockType sl (mLock);
for (auto const& e : mFeatureMap)
for (auto const& e : m_amendmentMap)
{
if (e.second.mVetoed)
ret.insert (e.first);
@@ -251,12 +251,12 @@ FeaturesImpl::getVetoed ()
return ret;
}
FeaturesImpl::featureList_t
FeaturesImpl::getEnabled ()
AmendmentTableImpl::amendmentList_t
AmendmentTableImpl::getEnabled ()
{
featureList_t ret;
amendmentList_t ret;
ScopedLockType sl (mLock);
for (auto const& e : mFeatureMap)
for (auto const& e : m_amendmentMap)
{
if (e.second.mEnabled)
ret.insert (e.first);
@@ -265,7 +265,8 @@ FeaturesImpl::getEnabled ()
}
bool
FeaturesImpl::shouldEnable (std::uint32_t closeTime, const FeatureState& fs)
AmendmentTableImpl::shouldEnable (std::uint32_t closeTime,
const AmendmentState& fs)
{
if (fs.mVetoed || fs.mEnabled || !fs.mSupported || (fs.m_lastMajority != m_lastReport))
return false;
@@ -280,15 +281,15 @@ FeaturesImpl::shouldEnable (std::uint32_t closeTime, const FeatureState& fs)
return (fs.m_lastMajority - fs.m_firstMajority) > m_majorityTime.count();
}
FeaturesImpl::featureList_t
FeaturesImpl::getToEnable (core::Clock::time_point closeTime)
AmendmentTableImpl::amendmentList_t
AmendmentTableImpl::getToEnable (core::Clock::time_point closeTime)
{
featureList_t ret;
amendmentList_t ret;
ScopedLockType sl (mLock);
if (m_lastReport != 0)
{
for (auto const& e : mFeatureMap)
for (auto const& e : m_amendmentMap)
{
if (shouldEnable (closeTime, e.second))
ret.insert (e.first);
@@ -298,13 +299,13 @@ FeaturesImpl::getToEnable (core::Clock::time_point closeTime)
return ret;
}
FeaturesImpl::featureList_t
FeaturesImpl::getDesired ()
AmendmentTableImpl::amendmentList_t
AmendmentTableImpl::getDesired ()
{
featureList_t ret;
amendmentList_t ret;
ScopedLockType sl (mLock);
for (auto const& e : mFeatureMap)
for (auto const& e : m_amendmentMap)
{
if (e.second.mSupported && !e.second.mEnabled && !e.second.mVetoed)
ret.insert (e.first);
@@ -314,7 +315,7 @@ FeaturesImpl::getDesired ()
}
void
FeaturesImpl::reportValidations (const FeatureSet& set)
AmendmentTableImpl::reportValidations (const AmendmentSet& set)
{
if (set.mTrustedValidations == 0)
return;
@@ -328,14 +329,14 @@ FeaturesImpl::reportValidations (const FeatureSet& set)
if (m_firstReport == 0)
m_firstReport = set.mCloseTime;
std::vector<uint256> changedFeatures;
changedFeatures.resize (set.mVotes.size ());
std::vector<uint256> changedAmendments;
changedAmendments.resize(set.mVotes.size());
for (auto const& e : set.mVotes)
{
FeatureState& state = mFeatureMap[e.first];
AmendmentState& state = m_amendmentMap[e.first];
if (m_journal.debug) m_journal.debug <<
"Feature " << e.first.GetHex () <<
"Amendment " << e.first.GetHex () <<
" has " << e.second <<
" votes, needs " << threshold;
@@ -347,11 +348,11 @@ FeaturesImpl::reportValidations (const FeatureSet& set)
if (state.m_firstMajority == 0)
{
if (m_journal.warning) m_journal.warning <<
"Feature " << e.first <<
"Amendment " << e.first <<
" attains a majority vote";
state.m_firstMajority = set.mCloseTime;
changedFeatures.push_back (e.first);
changedAmendments.push_back(e.first);
}
}
else // we have no majority
@@ -359,26 +360,26 @@ FeaturesImpl::reportValidations (const FeatureSet& set)
if (state.m_firstMajority != 0)
{
if (m_journal.warning) m_journal.warning <<
"Feature " << e.first <<
"Amendment " << e.first <<
" loses majority vote";
state.m_firstMajority = 0;
state.m_lastMajority = 0;
changedFeatures.push_back (e.first);
changedAmendments.push_back(e.first);
}
}
}
m_lastReport = set.mCloseTime;
if (!changedFeatures.empty ())
if (!changedAmendments.empty())
{
DeprecatedScopedLock sl (getApp().getWalletDB ()->getDBLock ());
Database* db = getApp().getWalletDB ()->getDB ();
db->executeSQL ("BEGIN TRANSACTION;");
for (auto const& hash : changedFeatures)
for (auto const& hash : changedAmendments)
{
FeatureState& fState = mFeatureMap[hash];
AmendmentState& fState = m_amendmentMap[hash];
db->executeSQL (boost::str (boost::format (
"UPDATE Features SET FirstMajority = %d WHERE Hash = '%s';"
) % fState.m_firstMajority % hash.GetHex ()));
@@ -387,63 +388,65 @@ FeaturesImpl::reportValidations (const FeatureSet& set)
) % fState.m_lastMajority % hash.GetHex()));
}
db->executeSQL ("END TRANSACTION;");
changedFeatures.clear ();
changedAmendments.clear();
}
}
void
FeaturesImpl::setEnabled (const std::vector<uint256>& features)
AmendmentTableImpl::setEnabled (const std::vector<uint256>& amendments)
{
ScopedLockType sl (mLock);
for (auto& e : mFeatureMap)
for (auto& e : m_amendmentMap)
{
e.second.mEnabled = false;
}
for (auto const& e : features)
for (auto const& e : amendments)
{
mFeatureMap[e].mEnabled = true;
m_amendmentMap[e].mEnabled = true;
}
}
void
FeaturesImpl::setSupported (const std::vector<uint256>& features)
AmendmentTableImpl::setSupported (const std::vector<uint256>& amendments)
{
ScopedLockType sl (mLock);
for (auto &e : mFeatureMap)
for (auto &e : m_amendmentMap)
{
e.second.mSupported = false;
}
for (auto const& e : features)
for (auto const& e : amendments)
{
mFeatureMap[e].mSupported = true;
m_amendmentMap[e].mSupported = true;
}
}
void
FeaturesImpl::doValidation (Ledger::ref lastClosedLedger, STObject& baseValidation)
AmendmentTableImpl::doValidation (Ledger::ref lastClosedLedger,
STObject& baseValidation)
{
featureList_t lFeatures = getDesired ();
amendmentList_t lAmendments = getDesired();
if (lFeatures.empty ())
if (lAmendments.empty())
return;
STVector256 vFeatures (sfFeatures);
for (auto const& uFeature : lFeatures)
STVector256 vAmendments (sfAmendments);
for (auto const& uAmendment : lAmendments)
{
vFeatures.addValue (uFeature);
vAmendments.addValue (uAmendment);
}
vFeatures.sort ();
baseValidation.setFieldV256 (sfFeatures, vFeatures);
vAmendments.sort ();
baseValidation.setFieldV256 (sfAmendments, vAmendments);
}
void
FeaturesImpl::doVoting (Ledger::ref lastClosedLedger, SHAMap::ref initialPosition)
AmendmentTableImpl::doVoting (Ledger::ref lastClosedLedger,
SHAMap::ref initialPosition)
{
// LCL must be flag ledger
assert((lastClosedLedger->getLedgerSeq () % 256) == 0);
FeatureSet featureSet (lastClosedLedger->getParentCloseTimeNC ());
AmendmentSet amendmentSet (lastClosedLedger->getParentCloseTimeNC ());
// get validations for ledger before flag ledger
ValidationSet valSet = getApp().getValidations ().getValidations (lastClosedLedger->getParentHash ());
@@ -453,29 +456,28 @@ FeaturesImpl::doVoting (Ledger::ref lastClosedLedger, SHAMap::ref initialPositio
if (val.isTrusted ())
{
featureSet.addVoter ();
if (val.isFieldPresent (sfFeatures))
amendmentSet.addVoter ();
if (val.isFieldPresent (sfAmendments))
{
for (auto const& feature : val.getFieldV256 (sfFeatures))
for (auto const& amendment : val.getFieldV256 (sfAmendments))
{
featureSet.addVote (feature);
amendmentSet.addVote (amendment);
}
}
}
}
reportValidations (featureSet);
reportValidations (amendmentSet);
featureList_t lFeatures = getToEnable (lastClosedLedger->getCloseTimeNC ());
for (auto const& uFeature : lFeatures)
amendmentList_t lAmendments = getToEnable (lastClosedLedger->getCloseTimeNC ());
for (auto const& uAmendment : lAmendments)
{
if (m_journal.warning) m_journal.warning <<
"Voting for feature: " << uFeature;
"Voting for amendment: " << uAmendment;
// Create the transaction to enable the feature
SerializedTransaction trans (ttFEATURE);
// Create the transaction to enable the amendment
SerializedTransaction trans (ttAMENDMENT);
trans.setFieldAccount (sfAccount, uint160 ());
trans.setFieldH256 (sfFeature, uFeature);
trans.setFieldH256 (sfAmendment, uAmendment);
uint256 txID = trans.getTransactionID ();
if (m_journal.warning) m_journal.warning <<
@@ -484,24 +486,24 @@ FeaturesImpl::doVoting (Ledger::ref lastClosedLedger, SHAMap::ref initialPositio
// Inject the transaction into our initial proposal
Serializer s;
trans.add (s, true);
#if RIPPLE_PROPOSE_FEATURES
#if RIPPLE_PROPOSE_AMENDMENTS
SHAMapItem::pointer tItem = boost::make_shared<SHAMapItem> (txID, s.peekData ());
if (!initialPosition->addGiveItem (tItem, true, false))
{
if (m_journal.warning) m_journal.warning <<
"Ledger already had feature transaction";
"Ledger already had amendment transaction";
}
#endif
}
}
Json::Value
FeaturesImpl::getJson (int)
AmendmentTableImpl::getJson (int)
{
Json::Value ret(Json::objectValue);
{
ScopedLockType sl(mLock);
for (auto const& e : mFeatureMap)
for (auto const& e : m_amendmentMap)
{
setJson (ret[e.first.GetHex ()] = Json::objectValue, e.second);
}
@@ -510,7 +512,7 @@ FeaturesImpl::getJson (int)
}
void
FeaturesImpl::setJson (Json::Value& v, const FeatureState& fs)
AmendmentTableImpl::setJson (Json::Value& v, const AmendmentState& fs)
{
if (!fs.mFriendlyName.empty())
v["name"] = fs.mFriendlyName;
@@ -556,26 +558,26 @@ FeaturesImpl::setJson (Json::Value& v, const FeatureState& fs)
}
Json::Value
FeaturesImpl::getJson (uint256 const& featureID)
AmendmentTableImpl::getJson (uint256 const& amendmentID)
{
Json::Value ret = Json::objectValue;
Json::Value& jFeature = (ret[featureID.GetHex()] = Json::objectValue);
Json::Value& jAmendment = (ret[amendmentID.GetHex ()] = Json::objectValue);
{
ScopedLockType sl(mLock);
FeatureState *featureState = getCreate (featureID, true);
setJson (jFeature, *featureState);
AmendmentState *amendmentState = getCreate (amendmentID, true);
setJson (jAmendment, *amendmentState);
}
return ret;
}
std::unique_ptr<FeatureTable>
make_FeatureTable (std::chrono::seconds majorityTime, int majorityFraction,
std::unique_ptr<AmendmentTable>
make_AmendmentTable (std::chrono::seconds majorityTime, int majorityFraction,
beast::Journal journal)
{
return std::make_unique<FeaturesImpl> (majorityTime, majorityFraction,
return std::make_unique<AmendmentTableImpl> (majorityTime, majorityFraction,
journal);
}

View File

@@ -58,7 +58,7 @@ public:
, mNeedNetworkLedger (false)
, mProposing (false)
, mValidating (false)
, mFeatureBlocked (false)
, m_amendmentBlocked (false)
, m_heartbeatTimer (this)
, m_clusterTimer (this)
, m_ledgerMaster (ledgerMaster)
@@ -299,11 +299,11 @@ public:
{
return mValidating;
}
bool isFeatureBlocked ()
bool isAmendmentBlocked ()
{
return mFeatureBlocked;
return m_amendmentBlocked;
}
void setFeatureBlocked ();
void setAmendmentBlocked ();
void consensusViewChange ();
int getPreviousProposers ()
{
@@ -469,7 +469,7 @@ private:
OperatingMode mMode;
bool mNeedNetworkLedger;
bool mProposing, mValidating;
bool mFeatureBlocked;
bool m_amendmentBlocked;
boost::posix_time::ptime mConnectTime;
beast::DeadlineTimer m_heartbeatTimer;
beast::DeadlineTimer m_clusterTimer;
@@ -1191,9 +1191,9 @@ Json::Value NetworkOPsImp::getOwnerInfo (Ledger::pointer lpLedger, const RippleA
// Other
//
void NetworkOPsImp::setFeatureBlocked ()
void NetworkOPsImp::setAmendmentBlocked ()
{
mFeatureBlocked = true;
m_amendmentBlocked = true;
setMode (omTRACKING);
}
@@ -1728,7 +1728,7 @@ void NetworkOPsImp::setMode (OperatingMode om)
om = omCONNECTED;
}
if ((om > omTRACKING) && mFeatureBlocked)
if ((om > omTRACKING) && m_amendmentBlocked)
om = omTRACKING;
if (mMode == om)
@@ -2207,8 +2207,8 @@ Json::Value NetworkOPsImp::getServerInfo (bool human, bool admin)
info["complete_ledgers"] = getApp().getLedgerMaster ().getCompleteLedgers ();
if (mFeatureBlocked)
info["feature_blocked"] = true;
if (m_amendmentBlocked)
info["amendment_blocked"] = true;
size_t fp = mFetchPack.getCacheSize ();

View File

@@ -251,8 +251,8 @@ public:
virtual void setProposing (bool isProposing, bool isValidating) = 0;
virtual bool isProposing () = 0;
virtual bool isValidating () = 0;
virtual bool isFeatureBlocked () = 0;
virtual void setFeatureBlocked () = 0;
virtual bool isAmendmentBlocked () = 0;
virtual void setAmendmentBlocked () = 0;
virtual void consensusViewChange () = 0;
virtual int getPreviousProposers () = 0;
virtual int getPreviousConvergeTime () = 0;

View File

@@ -0,0 +1,30 @@
# Amendment
An Amendment is a new or proposed change to a ledger rule. Ledger rules affect
transaction processing and consensus; peers must use the same set of rules for
consensus to succeed, otherwise different instances of rippled will get
different results. Amendments can be almost anything but they must be accepted
by a network majority through a consensus process before they are utilized. An
Amendment must receive at least an 80% approval rate from validating nodes for
a period of two weeks before being accepted. The following example outlines the
process of an Amendment from its conception to approval and usage.
* A community member makes proposes to change transaction processing in some
way. The proposal is discussed amongst the community and receives its support
creating a community or human consensus.
* Some members contribute their time and work to develop the Amendment.
* A pull request is created and the new code is folded into a rippled build
and made available for use.
* The consensus process begins with the validating nodes.
* If the Amendment holds an 80% majority for a two week period, nodes will begin
including the transaction to enable it in their initial sets.
Nodes may veto Amendments they consider undesirable by never announcing their
support for those Amendments. Just a few nodes vetoing an Amendment will normally
keep it from being accepted. Nodes could also vote yes on an Amendments even
before it obtains a super-majority. This might make sense for a critical bug fix.

View File

@@ -83,7 +83,7 @@
#include "main/LoadManager.h"
#include "misc/OrderBook.h"
#include "shamap/SHAMapSyncFilters.h"
#include "misc/FeatureTable.h"
#include "misc/AmendmentTable.h"
#include "misc/FeeVote.h"
#include "misc/IHashRouter.h"
#include "peers/ClusterNodeStatus.h"

View File

@@ -31,4 +31,4 @@
#include "misc/HashRouter.cpp"
#include "misc/Offer.cpp"
#include "paths/Pathfinder.cpp"
#include "misc/FeaturesImpl.cpp"
#include "misc/AmendmentTableImpl.cpp"

View File

@@ -21,8 +21,8 @@ namespace ripple {
TER ChangeTransactor::doApply ()
{
if (mTxn.getTxnType () == ttFEATURE)
return applyFeature ();
if (mTxn.getTxnType () == ttAMENDMENT)
return applyAmendment ();
if (mTxn.getTxnType () == ttFEE)
return applyFee ();
@@ -89,30 +89,32 @@ TER ChangeTransactor::preCheck ()
return tesSUCCESS;
}
TER ChangeTransactor::applyFeature ()
TER ChangeTransactor::applyAmendment ()
{
uint256 feature (mTxn.getFieldH256 (sfFeature));
uint256 amendment (mTxn.getFieldH256 (sfAmendment));
SLE::pointer featureObject (mEngine->entryCache (
ltFEATURES, Ledger::getLedgerFeatureIndex ()));
SLE::pointer amendmentObject (mEngine->entryCache (
ltAMENDMENTS, Ledger::getLedgerAmendmentIndex ()));
if (!featureObject)
featureObject = mEngine->entryCreate (
ltFEATURES, Ledger::getLedgerFeatureIndex ());
if (!amendmentObject)
{
amendmentObject = mEngine->entryCreate(
ltAMENDMENTS, Ledger::getLedgerAmendmentIndex());
}
STVector256 features (featureObject->getFieldV256 (sfFeatures));
STVector256 amendments (amendmentObject->getFieldV256 (sfAmendments));
if (features.hasValue (feature))
if (amendments.hasValue (amendment))
return tefALREADY;
features.addValue (feature);
featureObject->setFieldV256 (sfFeatures, features);
mEngine->entryModify (featureObject);
amendments.addValue (amendment);
amendmentObject->setFieldV256 (sfAmendments, amendments);
mEngine->entryModify (amendmentObject);
getApp().getFeatureTable ().enable (feature);
getApp().getAmendmentTable ().enable (amendment);
if (!getApp().getFeatureTable ().isSupported (feature))
getApp().getOPs ().setFeatureBlocked ();
if (!getApp().getAmendmentTable ().isSupported (amendment))
getApp().getOPs ().setAmendmentBlocked ();
return tesSUCCESS;
}

View File

@@ -54,7 +54,7 @@ public:
TER preCheck () override;
private:
TER applyFeature ();
TER applyAmendment ();
TER applyFee ();
// VFALCO TODO Can this be removed?

View File

@@ -64,7 +64,7 @@ std::unique_ptr<Transactor> Transactor::makeTransactor (
return std::unique_ptr<Transactor> (
new WalletAddTransactor (txn, params, engine));
case ttFEATURE:
case ttAMENDMENT:
case ttFEE:
return std::unique_ptr<Transactor> (
new ChangeTransactor (txn, params, engine));

View File

@@ -108,8 +108,8 @@ LedgerFormats::LedgerFormats ()
<< SOElement (sfHashes, SOE_REQUIRED)
;
add ("EnabledFeatures", ltFEATURES)
<< SOElement (sfFeatures, SOE_REQUIRED)
add ("EnabledAmendments", ltAMENDMENTS)
<< SOElement (sfAmendments, SOE_REQUIRED)
;
add ("FeeSettings", ltFEE_SETTINGS)

View File

@@ -65,7 +65,7 @@ enum LedgerEntryType
ltLEDGER_HASHES = 'h',
ltFEATURES = 'f',
ltAMENDMENTS = 'f',
ltFEE_SETTINGS = 's',
};
@@ -87,7 +87,7 @@ enum LedgerNameSpace
spaceBookDir = 'B', // Directory of order books.
spaceContract = 'c',
spaceSkipList = 's',
spaceFeature = 'f',
spaceAmendment = 'f',
spaceFee = 'e',
};

View File

@@ -124,7 +124,7 @@ FIELD (AccountTxnID, HASH256, 9)
FIELD (BookDirectory, HASH256, 16)
FIELD (InvoiceID, HASH256, 17)
FIELD (Nickname, HASH256, 18)
FIELD (Feature, HASH256, 19)
FIELD (Amendment, HASH256, 19)
// 160-bit (common)
FIELD (TakerPaysCurrency, HASH160, 1)
@@ -177,7 +177,7 @@ FIELD (Paths, PATHSET, 1)
// vector of 256-bit
FIELD (Indexes, VECTOR256, 1)
FIELD (Hashes, VECTOR256, 2)
FIELD (Features, VECTOR256, 3)
FIELD (Amendments, VECTOR256, 3)
// inner object
// OBJECT/1 is reserved for end of object

View File

@@ -77,8 +77,8 @@ TxFormats::TxFormats ()
<< SOElement (sfTarget, SOE_REQUIRED)
;
add ("EnableFeature", ttFEATURE)
<< SOElement (sfFeature, SOE_REQUIRED)
add ("EnableAmendment", ttAMENDMENT)
<< SOElement (sfAmendment, SOE_REQUIRED)
;
add ("SetFee", ttFEE)

View File

@@ -46,7 +46,7 @@ enum TxType
ttTRUST_SET = 20,
ttFEATURE = 100,
ttAMENDMENT = 100,
ttFEE = 101,
};

View File

@@ -45,11 +45,11 @@ Json::Value RPCHandler::doFeature (Json::Value params, Resource::Charge& loadTyp
if (!params.isMember ("feature"))
{
Json::Value jvReply = Json::objectValue;
jvReply["features"] = getApp().getFeatureTable ().getJson (0);
jvReply["features"] = getApp().getAmendmentTable ().getJson(0);
return jvReply;
}
uint256 uFeature = getApp().getFeatureTable ().get (params["feature"].asString ());
uint256 uFeature = getApp().getAmendmentTable ().get(params["feature"].asString());
if (uFeature.isZero ())
{
@@ -60,7 +60,7 @@ Json::Value RPCHandler::doFeature (Json::Value params, Resource::Charge& loadTyp
}
if (!params.isMember ("vote"))
return getApp().getFeatureTable ().getJson (uFeature);
return getApp().getAmendmentTable ().getJson(uFeature);
// WRITEME
return rpcError (rpcNOT_SUPPORTED);