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)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile> </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)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">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\AccountItems.h" />
<ClInclude Include="..\..\src\ripple_app\misc\AccountState.h" /> <ClInclude Include="..\..\src\ripple_app\misc\AccountState.h" />
<ClInclude Include="..\..\src\ripple_app\misc\CanonicalTXSet.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\FeeVote.h" />
<ClInclude Include="..\..\src\ripple_app\misc\IHashRouter.h" /> <ClInclude Include="..\..\src\ripple_app\misc\IHashRouter.h" />
<ClInclude Include="..\..\src\ripple_app\misc\ProofOfWorkFactory.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\TODO.md" />
<None Include="..\..\src\ripple\validators\README.md" /> <None Include="..\..\src\ripple\validators\README.md" />
<None Include="..\..\src\ripple_app\ledger\TODO.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_app\TODO.md" />
<None Include="..\..\src\ripple_core\nodestore\README.md" /> <None Include="..\..\src\ripple_core\nodestore\README.md" />
<None Include="..\..\src\ripple_overlay\README.md" /> <None Include="..\..\src\ripple_overlay\README.md" />

View File

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

View File

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

View File

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

View File

@@ -1504,11 +1504,11 @@ uint256 Ledger::getLedgerFeeIndex ()
return s.getSHA512Half (); 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); Serializer s (2);
s.add16 (spaceFeature); s.add16 (spaceAmendment);
return s.getSHA512Half (); return s.getSHA512Half ();
} }
@@ -1616,15 +1616,15 @@ std::vector< std::pair<std::uint32_t, uint256> > Ledger::getLedgerHashes ()
return ret; return ret;
} }
std::vector<uint256> Ledger::getLedgerFeatures () std::vector<uint256> Ledger::getLedgerAmendments ()
{ {
std::vector<uint256> usFeatures; std::vector<uint256> usAmendments;
SLE::pointer sleFeatures = getSLEi (getLedgerFeatureIndex ()); SLE::pointer sleAmendments = getSLEi (getLedgerAmendmentIndex ());
if (sleFeatures) if (sleAmendments)
usFeatures = sleFeatures->getFieldV256 (sfFeatures).peekValue (); usAmendments = sleAmendments->getFieldV256 (sfAmendments).peekValue ();
return usFeatures; return usAmendments;
} }
// XRP to XRP not allowed. // XRP to XRP not allowed.

View File

@@ -300,9 +300,9 @@ public:
uint256 getLedgerHash (std::uint32_t ledgerIndex); uint256 getLedgerHash (std::uint32_t ledgerIndex);
std::vector< std::pair<std::uint32_t, uint256> > getLedgerHashes (); std::vector< std::pair<std::uint32_t, uint256> > getLedgerHashes ();
static uint256 getLedgerFeatureIndex (); static uint256 getLedgerAmendmentIndex ();
static uint256 getLedgerFeeIndex (); static uint256 getLedgerFeeIndex ();
std::vector<uint256> getLedgerFeatures (); std::vector<uint256> getLedgerAmendments ();
std::vector<uint256> getNeededTransactionHashes (int max, SHAMapSyncFilter * filter); std::vector<uint256> getNeededTransactionHashes (int max, SHAMapSyncFilter * filter);
std::vector<uint256> getNeededAccountStateHashes (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 (sfLedgerSequence, SOE_OPTIONAL));
format.push_back (SOElement (sfCloseTime, SOE_OPTIONAL)); format.push_back (SOElement (sfCloseTime, SOE_OPTIONAL));
format.push_back (SOElement (sfLoadFee, 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 (sfBaseFee, SOE_OPTIONAL));
format.push_back (SOElement (sfReserveBase, SOE_OPTIONAL)); format.push_back (SOElement (sfReserveBase, SOE_OPTIONAL));
format.push_back (SOElement (sfReserveIncrement, SOE_OPTIONAL)); format.push_back (SOElement (sfReserveIncrement, SOE_OPTIONAL));

View File

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

View File

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

View File

@@ -17,22 +17,22 @@
*/ */
//============================================================================== //==============================================================================
#ifndef RIPPLE_FEATURES_H #ifndef RIPPLE_AMENDMENT_TABLE_H
#define RIPPLE_FEATURES_H #define RIPPLE_AMENDMENT_TABLE_H
#include "../book/Types.h" #include "../book/Types.h"
namespace ripple { 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: public:
std::uint32_t mCloseTime; std::uint32_t mCloseTime;
int mTrustedValidations; // number of trusted validations 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; ++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: public:
bool mVetoed; // We don't want this feature enabled bool mVetoed; // We don't want this amendment enabled
bool mEnabled; bool mEnabled;
bool mSupported; bool mSupported;
bool mDefault; // Include in genesis ledger bool mDefault; // Include in genesis ledger
@@ -59,7 +63,7 @@ public:
std::string mFriendlyName; std::string mFriendlyName;
FeatureState () AmendmentState ()
: mVetoed (false), mEnabled (false), mSupported (false), mDefault (false), : mVetoed (false), mEnabled (false), mSupported (false), mDefault (false),
m_firstMajority (0), m_lastMajority (0) m_firstMajority (0), m_lastMajority (0)
{ {
@@ -100,46 +104,44 @@ public:
} }
}; };
/** Feature table interface. /** The amendment table stores the list of enabled and potential amendments.
Individuals amendments are voted on by validators during the consensus
The feature table stores the list of enabled and potential features.
Individuals features are voted on by validators during the consensus
process. process.
*/ */
class FeatureTable class AmendmentTable
{ {
public: 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. before we're willing to vote yes on it.
@param majorityFraction ratio, out of 256, of servers that must say @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. have a majority.
@param journal @param journal
*/ */
virtual ~FeatureTable() { } virtual ~AmendmentTable() { }
virtual void addInitial () = 0; virtual void addInitial () = 0;
virtual FeatureState* addKnown (const char* featureID, virtual AmendmentState* addKnown (const char* amendmentID,
const char* friendlyName, bool veto) = 0; const char* friendlyName, bool veto) = 0;
virtual uint256 get (const std::string& name) = 0; virtual uint256 get (const std::string& name) = 0;
virtual bool veto (uint256 const& feature) = 0; virtual bool veto (uint256 const& amendment) = 0;
virtual bool unVeto (uint256 const& feature) = 0; virtual bool unVeto (uint256 const& amendment) = 0;
virtual bool enable (uint256 const& feature) = 0; virtual bool enable (uint256 const& amendment) = 0;
virtual bool disable (uint256 const& feature) = 0; virtual bool disable (uint256 const& amendment) = 0;
virtual bool isEnabled (uint256 const& feature) = 0; virtual bool isEnabled (uint256 const& amendment) = 0;
virtual bool isSupported (uint256 const& feature) = 0; virtual bool isSupported (uint256 const& amendment) = 0;
virtual void setEnabled (const std::vector<uint256>& features) = 0; virtual void setEnabled (const std::vector<uint256>& amendments) = 0;
virtual void setSupported (const std::vector<uint256>& features) = 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 (int) = 0;
virtual Json::Value getJson (uint256 const& ) = 0; virtual Json::Value getJson (uint256 const& ) = 0;
@@ -150,8 +152,8 @@ public:
doVoting (Ledger::ref lastClosedLedger, SHAMap::ref initialPosition) = 0; doVoting (Ledger::ref lastClosedLedger, SHAMap::ref initialPosition) = 0;
}; };
std::unique_ptr<FeatureTable> std::unique_ptr<AmendmentTable>
make_FeatureTable (std::chrono::seconds majorityTime, int majorityFraction, make_AmendmentTable (std::chrono::seconds majorityTime, int majorityFraction,
beast::Journal journal); beast::Journal journal);
} // ripple } // ripple

View File

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

View File

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

View File

@@ -251,8 +251,8 @@ public:
virtual void setProposing (bool isProposing, bool isValidating) = 0; virtual void setProposing (bool isProposing, bool isValidating) = 0;
virtual bool isProposing () = 0; virtual bool isProposing () = 0;
virtual bool isValidating () = 0; virtual bool isValidating () = 0;
virtual bool isFeatureBlocked () = 0; virtual bool isAmendmentBlocked () = 0;
virtual void setFeatureBlocked () = 0; virtual void setAmendmentBlocked () = 0;
virtual void consensusViewChange () = 0; virtual void consensusViewChange () = 0;
virtual int getPreviousProposers () = 0; virtual int getPreviousProposers () = 0;
virtual int getPreviousConvergeTime () = 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 "main/LoadManager.h"
#include "misc/OrderBook.h" #include "misc/OrderBook.h"
#include "shamap/SHAMapSyncFilters.h" #include "shamap/SHAMapSyncFilters.h"
#include "misc/FeatureTable.h" #include "misc/AmendmentTable.h"
#include "misc/FeeVote.h" #include "misc/FeeVote.h"
#include "misc/IHashRouter.h" #include "misc/IHashRouter.h"
#include "peers/ClusterNodeStatus.h" #include "peers/ClusterNodeStatus.h"

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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