mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Reorganize source file hierarchy:
* Rename unity files * Move some modules to new subdirectories * Remove obsolete Visual Studio project files * Remove obsolete coding style and TODO list
This commit is contained in:
28
src/ripple/module/app/misc/AccountItem.cpp
Normal file
28
src/ripple/module/app/misc/AccountItem.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
namespace ripple {
|
||||
|
||||
AccountItem::AccountItem (SerializedLedgerEntry::ref ledger)
|
||||
: mLedgerEntry (ledger)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
} // ripple
|
||||
91
src/ripple/module/app/misc/AccountItem.h
Normal file
91
src/ripple/module/app/misc/AccountItem.h
Normal file
@@ -0,0 +1,91 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_ACCOUNTITEM_H
|
||||
#define RIPPLE_ACCOUNTITEM_H
|
||||
|
||||
namespace ripple {
|
||||
|
||||
//
|
||||
// Fetch ledger entries from an account's owner dir.
|
||||
//
|
||||
/** Base class representing account items.
|
||||
|
||||
Account items include:
|
||||
|
||||
- Offers
|
||||
- Trust Lines
|
||||
|
||||
NOTE these are deprecated and will go away, to be replaced with
|
||||
simple visitor patterns.
|
||||
*/
|
||||
class AccountItem
|
||||
{
|
||||
public:
|
||||
typedef boost::shared_ptr <AccountItem> pointer;
|
||||
typedef const pointer& ref;
|
||||
|
||||
public:
|
||||
AccountItem ()
|
||||
{ }
|
||||
|
||||
/** Construct from a flat ledger entry.
|
||||
*/
|
||||
explicit AccountItem (SerializedLedgerEntry::ref ledger);
|
||||
|
||||
virtual ~AccountItem ()
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
virtual AccountItem::pointer makeItem (const uint160& accountID, SerializedLedgerEntry::ref ledgerEntry) = 0;
|
||||
|
||||
// VFALCO TODO Make this const and change derived classes
|
||||
virtual LedgerEntryType getType () = 0;
|
||||
|
||||
// VFALCO TODO Document the int parameter
|
||||
virtual Json::Value getJson (int) = 0;
|
||||
|
||||
SerializedLedgerEntry::pointer getSLE ()
|
||||
{
|
||||
return mLedgerEntry;
|
||||
}
|
||||
|
||||
const SerializedLedgerEntry& peekSLE () const
|
||||
{
|
||||
return *mLedgerEntry;
|
||||
}
|
||||
|
||||
SerializedLedgerEntry& peekSLE ()
|
||||
{
|
||||
return *mLedgerEntry;
|
||||
}
|
||||
|
||||
Blob getRaw () const;
|
||||
|
||||
// VFALCO TODO Make this private and use the existing accessors
|
||||
//
|
||||
protected:
|
||||
// VFALCO TODO Research making the object pointed to const
|
||||
SerializedLedgerEntry::pointer mLedgerEntry;
|
||||
};
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
93
src/ripple/module/app/misc/AccountItems.cpp
Normal file
93
src/ripple/module/app/misc/AccountItems.cpp
Normal file
@@ -0,0 +1,93 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
namespace ripple {
|
||||
|
||||
AccountItems::AccountItems (uint160 const& accountID,
|
||||
Ledger::ref ledger,
|
||||
AccountItem::pointer ofType)
|
||||
{
|
||||
mOfType = ofType;
|
||||
|
||||
fillItems (accountID, ledger);
|
||||
}
|
||||
|
||||
void AccountItems::fillItems (const uint160& accountID, Ledger::ref ledger)
|
||||
{
|
||||
uint256 const rootIndex = Ledger::getOwnerDirIndex (accountID);
|
||||
uint256 currentIndex = rootIndex;
|
||||
|
||||
// VFALCO TODO Rewrite all infinite loops to have clear terminating
|
||||
// conditions defined in one location.
|
||||
//
|
||||
while (1)
|
||||
{
|
||||
SLE::pointer ownerDir = ledger->getDirNode (currentIndex);
|
||||
|
||||
// VFALCO TODO Rewrite to not return from the middle of the function
|
||||
if (!ownerDir)
|
||||
return;
|
||||
|
||||
BOOST_FOREACH (uint256 const & uNode, ownerDir->getFieldV256 (sfIndexes).peekValue ())
|
||||
{
|
||||
// VFALCO TODO rename getSLEi() to something legible.
|
||||
SLE::pointer sleCur = ledger->getSLEi (uNode);
|
||||
|
||||
if (!sleCur)
|
||||
{
|
||||
// item in directory not in ledger
|
||||
}
|
||||
else
|
||||
{
|
||||
AccountItem::pointer item = mOfType->makeItem (accountID, sleCur);
|
||||
|
||||
// VFALCO NOTE Under what conditions would makeItem() return nullptr?
|
||||
// DJS NOTE If the item wasn't one this particular AccountItems was interested in
|
||||
// (For example, if the owner is only interested in ripple lines and this is an offer)
|
||||
if (item)
|
||||
{
|
||||
mItems.push_back (item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::uint64_t uNodeNext = ownerDir->getFieldU64 (sfIndexNext);
|
||||
|
||||
// VFALCO TODO Rewrite to not return from the middle of the function
|
||||
if (!uNodeNext)
|
||||
return;
|
||||
|
||||
currentIndex = Ledger::getDirNodeIndex (rootIndex, uNodeNext);
|
||||
}
|
||||
}
|
||||
|
||||
Json::Value AccountItems::getJson (int v)
|
||||
{
|
||||
Json::Value ret (Json::arrayValue);
|
||||
|
||||
BOOST_FOREACH (AccountItem::ref ai, mItems)
|
||||
{
|
||||
ret.append (ai->getJson (v));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // ripple
|
||||
|
||||
61
src/ripple/module/app/misc/AccountItems.h
Normal file
61
src/ripple/module/app/misc/AccountItems.h
Normal file
@@ -0,0 +1,61 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_ACCOUNTITEMS_H
|
||||
#define RIPPLE_ACCOUNTITEMS_H
|
||||
|
||||
namespace ripple {
|
||||
|
||||
/** A set of AccountItem objects. */
|
||||
class AccountItems : beast::LeakChecked <AccountItems>
|
||||
{
|
||||
public:
|
||||
typedef boost::shared_ptr <AccountItems> pointer;
|
||||
|
||||
typedef std::vector <AccountItem::pointer> Container;
|
||||
|
||||
// VFALCO TODO Create a typedef uint160 AccountID and replace
|
||||
AccountItems (uint160 const& accountID,
|
||||
Ledger::ref ledger,
|
||||
AccountItem::pointer ofType);
|
||||
|
||||
// VFALCO TODO rename to getContainer and make this change in every interface
|
||||
// that exposes the caller to the type of container.
|
||||
//
|
||||
Container& getItems ()
|
||||
{
|
||||
return mItems;
|
||||
}
|
||||
|
||||
// VFALCO TODO What is the int for?
|
||||
Json::Value getJson (int);
|
||||
|
||||
private:
|
||||
void fillItems (const uint160& accountID, Ledger::ref ledger);
|
||||
|
||||
private:
|
||||
// VFALCO TODO This looks like its used as an exemplar, rename appropriately
|
||||
AccountItem::pointer mOfType;
|
||||
|
||||
Container mItems;
|
||||
};
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
84
src/ripple/module/app/misc/AccountState.cpp
Normal file
84
src/ripple/module/app/misc/AccountState.cpp
Normal file
@@ -0,0 +1,84 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
namespace ripple {
|
||||
|
||||
AccountState::AccountState (RippleAddress const& naAccountID)
|
||||
: mAccountID (naAccountID)
|
||||
, mValid (false)
|
||||
{
|
||||
if (naAccountID.isValid ())
|
||||
{
|
||||
mValid = true;
|
||||
|
||||
mLedgerEntry = boost::make_shared <SerializedLedgerEntry> (
|
||||
ltACCOUNT_ROOT, Ledger::getAccountRootIndex (naAccountID));
|
||||
|
||||
mLedgerEntry->setFieldAccount (sfAccount, naAccountID.getAccountID ());
|
||||
}
|
||||
}
|
||||
|
||||
AccountState::AccountState (SLE::ref ledgerEntry, const RippleAddress& naAccountID) :
|
||||
mAccountID (naAccountID), mLedgerEntry (ledgerEntry), mValid (false)
|
||||
{
|
||||
if (!mLedgerEntry)
|
||||
return;
|
||||
|
||||
if (mLedgerEntry->getType () != ltACCOUNT_ROOT)
|
||||
return;
|
||||
|
||||
mValid = true;
|
||||
}
|
||||
|
||||
// VFALCO TODO Make this a generic utility function of some container class
|
||||
//
|
||||
std::string AccountState::createGravatarUrl (uint128 uEmailHash)
|
||||
{
|
||||
Blob vucMD5 (uEmailHash.begin (), uEmailHash.end ());
|
||||
std::string strMD5Lower = strHex (vucMD5);
|
||||
boost::to_lower (strMD5Lower);
|
||||
|
||||
// VFALCO TODO Give a name and move this constant to a more visible location.
|
||||
// Also shouldn't this be https?
|
||||
return str (boost::format ("http://www.gravatar.com/avatar/%s") % strMD5Lower);
|
||||
}
|
||||
|
||||
void AccountState::addJson (Json::Value& val)
|
||||
{
|
||||
val = mLedgerEntry->getJson (0);
|
||||
|
||||
if (mValid)
|
||||
{
|
||||
if (mLedgerEntry->isFieldPresent (sfEmailHash))
|
||||
val["urlgravatar"] = createGravatarUrl (mLedgerEntry->getFieldH128 (sfEmailHash));
|
||||
}
|
||||
else
|
||||
{
|
||||
val["Invalid"] = true;
|
||||
}
|
||||
}
|
||||
|
||||
void AccountState::dump ()
|
||||
{
|
||||
Json::Value j (Json::objectValue);
|
||||
addJson (j);
|
||||
Log (lsINFO) << j;
|
||||
}
|
||||
|
||||
} // ripple
|
||||
94
src/ripple/module/app/misc/AccountState.h
Normal file
94
src/ripple/module/app/misc/AccountState.h
Normal file
@@ -0,0 +1,94 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_ACCOUNTSTATE_H
|
||||
#define RIPPLE_ACCOUNTSTATE_H
|
||||
|
||||
namespace ripple {
|
||||
|
||||
//
|
||||
// Provide abstract access to an account's state, such that access to the serialized format is hidden.
|
||||
//
|
||||
|
||||
class AccountState : beast::LeakChecked <AccountState>
|
||||
{
|
||||
public:
|
||||
typedef boost::shared_ptr<AccountState> pointer;
|
||||
|
||||
public:
|
||||
// For new accounts
|
||||
explicit AccountState (RippleAddress const& naAccountID);
|
||||
|
||||
// For accounts in a ledger
|
||||
AccountState (SLE::ref ledgerEntry, RippleAddress const& naAccountI);
|
||||
|
||||
bool haveAuthorizedKey ()
|
||||
{
|
||||
return mLedgerEntry->isFieldPresent (sfRegularKey);
|
||||
}
|
||||
|
||||
RippleAddress getAuthorizedKey ()
|
||||
{
|
||||
return mLedgerEntry->getFieldAccount (sfRegularKey);
|
||||
}
|
||||
|
||||
STAmount getBalance () const
|
||||
{
|
||||
return mLedgerEntry->getFieldAmount (sfBalance);
|
||||
}
|
||||
|
||||
std::uint32_t getSeq () const
|
||||
{
|
||||
return mLedgerEntry->getFieldU32 (sfSequence);
|
||||
}
|
||||
|
||||
SerializedLedgerEntry::pointer getSLE ()
|
||||
{
|
||||
return mLedgerEntry;
|
||||
}
|
||||
|
||||
SerializedLedgerEntry const& peekSLE () const
|
||||
{
|
||||
return *mLedgerEntry;
|
||||
}
|
||||
|
||||
SerializedLedgerEntry& peekSLE ()
|
||||
{
|
||||
return *mLedgerEntry;
|
||||
}
|
||||
|
||||
Blob getRaw () const;
|
||||
|
||||
void addJson (Json::Value& value);
|
||||
|
||||
void dump ();
|
||||
|
||||
static std::string createGravatarUrl (uint128 uEmailHash);
|
||||
|
||||
private:
|
||||
RippleAddress const mAccountID;
|
||||
RippleAddress mAuthorizedKey;
|
||||
SerializedLedgerEntry::pointer mLedgerEntry;
|
||||
|
||||
bool mValid;
|
||||
};
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
161
src/ripple/module/app/misc/AmendmentTable.h
Normal file
161
src/ripple/module/app/misc/AmendmentTable.h
Normal file
@@ -0,0 +1,161 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_AMENDMENT_TABLE_H
|
||||
#define RIPPLE_AMENDMENT_TABLE_H
|
||||
|
||||
#include <ripple/module/app/book/Types.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
/** The status of all amendments requested in a given window. */
|
||||
class AmendmentSet
|
||||
{
|
||||
public:
|
||||
std::uint32_t mCloseTime;
|
||||
int mTrustedValidations; // number of trusted validations
|
||||
ripple::unordered_map<uint256, int> mVotes; // yes votes by amendment
|
||||
|
||||
AmendmentSet (std::uint32_t ct) : mCloseTime (ct), mTrustedValidations (0)
|
||||
{
|
||||
;
|
||||
}
|
||||
void addVoter ()
|
||||
{
|
||||
++mTrustedValidations;
|
||||
}
|
||||
void addVote (uint256 const& amendment)
|
||||
{
|
||||
++mVotes[amendment];
|
||||
}
|
||||
};
|
||||
|
||||
/** 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 amendment enabled
|
||||
bool mEnabled;
|
||||
bool mSupported;
|
||||
bool mDefault; // Include in genesis ledger
|
||||
|
||||
core::Clock::time_point m_firstMajority; // First time we saw a majority (close time)
|
||||
core::Clock::time_point m_lastMajority; // Most recent time we saw a majority (close time)
|
||||
|
||||
std::string mFriendlyName;
|
||||
|
||||
AmendmentState ()
|
||||
: mVetoed (false), mEnabled (false), mSupported (false), mDefault (false),
|
||||
m_firstMajority (0), m_lastMajority (0)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
void setVeto ()
|
||||
{
|
||||
mVetoed = true;
|
||||
}
|
||||
void setDefault ()
|
||||
{
|
||||
mDefault = true;
|
||||
}
|
||||
bool isDefault ()
|
||||
{
|
||||
return mDefault;
|
||||
}
|
||||
bool isSupported ()
|
||||
{
|
||||
return mSupported;
|
||||
}
|
||||
bool isVetoed ()
|
||||
{
|
||||
return mVetoed;
|
||||
}
|
||||
bool isEnabled ()
|
||||
{
|
||||
return mEnabled;
|
||||
}
|
||||
const std::string& getFiendlyName ()
|
||||
{
|
||||
return mFriendlyName;
|
||||
}
|
||||
void setFriendlyName (const std::string& n)
|
||||
{
|
||||
mFriendlyName = n;
|
||||
}
|
||||
};
|
||||
|
||||
/** The amendment table stores the list of enabled and potential amendments.
|
||||
Individuals amendments are voted on by validators during the consensus
|
||||
process.
|
||||
*/
|
||||
class AmendmentTable
|
||||
{
|
||||
public:
|
||||
/** Create a new AmendmentTable.
|
||||
|
||||
@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 an amendment before we consider it to
|
||||
have a majority.
|
||||
@param journal
|
||||
*/
|
||||
|
||||
virtual ~AmendmentTable() { }
|
||||
|
||||
virtual void addInitial () = 0;
|
||||
|
||||
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& amendment) = 0;
|
||||
virtual bool unVeto (uint256 const& amendment) = 0;
|
||||
|
||||
virtual bool enable (uint256 const& amendment) = 0;
|
||||
virtual bool disable (uint256 const& amendment) = 0;
|
||||
|
||||
virtual bool isEnabled (uint256 const& amendment) = 0;
|
||||
virtual bool isSupported (uint256 const& amendment) = 0;
|
||||
|
||||
virtual void setEnabled (const std::vector<uint256>& amendments) = 0;
|
||||
virtual void setSupported (const std::vector<uint256>& amendments) = 0;
|
||||
|
||||
virtual void reportValidations (const AmendmentSet&) = 0;
|
||||
|
||||
virtual Json::Value getJson (int) = 0;
|
||||
virtual Json::Value getJson (uint256 const& ) = 0;
|
||||
|
||||
virtual void
|
||||
doValidation (Ledger::ref lastClosedLedger, STObject& baseValidation) = 0;
|
||||
virtual void
|
||||
doVoting (Ledger::ref lastClosedLedger, SHAMap::ref initialPosition) = 0;
|
||||
};
|
||||
|
||||
std::unique_ptr<AmendmentTable>
|
||||
make_AmendmentTable (std::chrono::seconds majorityTime, int majorityFraction,
|
||||
beast::Journal journal);
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
584
src/ripple/module/app/misc/AmendmentTableImpl.cpp
Normal file
584
src/ripple/module/app/misc/AmendmentTableImpl.cpp
Normal file
@@ -0,0 +1,584 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
namespace ripple {
|
||||
|
||||
/** Track the list of "amendments"
|
||||
|
||||
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 AmendmentTableImpl : public AmendmentTable
|
||||
{
|
||||
protected:
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
AmendmentState* getCreate (uint256 const& amendment, bool create);
|
||||
bool shouldEnable (std::uint32_t closeTime, const AmendmentState& fs);
|
||||
void setJson (Json::Value& v, const AmendmentState&);
|
||||
|
||||
public:
|
||||
|
||||
AmendmentTableImpl (std::chrono::seconds majorityTime, int majorityFraction,
|
||||
beast::Journal journal)
|
||||
: m_majorityTime (majorityTime)
|
||||
, mMajorityFraction (majorityFraction)
|
||||
, m_firstReport (0)
|
||||
, m_lastReport (0)
|
||||
, m_journal (journal)
|
||||
{
|
||||
}
|
||||
|
||||
void addInitial () override;
|
||||
|
||||
AmendmentState* addKnown (const char* amendmentID, const char* friendlyName,
|
||||
bool veto) override;
|
||||
uint256 get (const std::string& name) override;
|
||||
|
||||
bool veto (uint256 const& amendment) override;
|
||||
bool unVeto (uint256 const& amendment) override;
|
||||
|
||||
bool enable (uint256 const& amendment) override;
|
||||
bool disable (uint256 const& amendment) override;
|
||||
|
||||
bool isEnabled (uint256 const& amendment) override;
|
||||
bool isSupported (uint256 const& amendment) override;
|
||||
|
||||
void setEnabled (const std::vector<uint256>& amendments) override;
|
||||
void setSupported (const std::vector<uint256>& amendments) override;
|
||||
|
||||
void reportValidations (const AmendmentSet&) override;
|
||||
|
||||
Json::Value getJson (int) override;
|
||||
Json::Value getJson (uint256 const&) override;
|
||||
|
||||
void doValidation (Ledger::ref lastClosedLedger, STObject& baseValidation) override;
|
||||
void doVoting (Ledger::ref lastClosedLedger, SHAMap::ref initialPosition) override;
|
||||
|
||||
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
|
||||
AmendmentTableImpl::addInitial ()
|
||||
{
|
||||
// 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
|
||||
}
|
||||
|
||||
AmendmentState*
|
||||
AmendmentTableImpl::getCreate (uint256 const& amendmentHash, bool create)
|
||||
{
|
||||
// call with the mutex held
|
||||
auto iter (m_amendmentMap.find (amendmentHash));
|
||||
|
||||
if (iter == m_amendmentMap.end())
|
||||
{
|
||||
if (!create)
|
||||
return nullptr;
|
||||
|
||||
AmendmentState* amendment = & (m_amendmentMap[amendmentHash]);
|
||||
|
||||
{
|
||||
std::string query = "SELECT FirstMajority,LastMajority FROM Features WHERE hash='";
|
||||
query.append (to_string (amendmentHash));
|
||||
query.append ("';");
|
||||
|
||||
DeprecatedScopedLock sl (getApp().getWalletDB ()->getDBLock ());
|
||||
Database* db = getApp().getWalletDB ()->getDB ();
|
||||
|
||||
if (db->executeSQL (query) && db->startIterRows ())
|
||||
{
|
||||
amendment->m_firstMajority = db->getBigInt("FirstMajority");
|
||||
amendment->m_lastMajority = db->getBigInt("LastMajority");
|
||||
db->endIterRows ();
|
||||
}
|
||||
}
|
||||
|
||||
return amendment;
|
||||
}
|
||||
|
||||
return & (iter->second);
|
||||
}
|
||||
|
||||
uint256
|
||||
AmendmentTableImpl::get (const std::string& name)
|
||||
{
|
||||
for (auto const& e : m_amendmentMap)
|
||||
{
|
||||
if (name == e.second.mFriendlyName)
|
||||
return e.first;
|
||||
}
|
||||
|
||||
return uint256 ();
|
||||
}
|
||||
|
||||
AmendmentState*
|
||||
AmendmentTableImpl::addKnown (const char* amendmentID, const char* friendlyName,
|
||||
bool veto)
|
||||
{
|
||||
uint256 hash;
|
||||
hash.SetHex (amendmentID);
|
||||
|
||||
if (hash.isZero ())
|
||||
{
|
||||
assert (false);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AmendmentState* f = getCreate (hash, true);
|
||||
|
||||
if (friendlyName != nullptr)
|
||||
f->setFriendlyName (friendlyName);
|
||||
|
||||
f->mVetoed = veto;
|
||||
f->mSupported = true;
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
bool
|
||||
AmendmentTableImpl::veto (uint256 const& amendment)
|
||||
{
|
||||
ScopedLockType sl (mLock);
|
||||
AmendmentState* s = getCreate (amendment, true);
|
||||
|
||||
if (s->mVetoed)
|
||||
return false;
|
||||
|
||||
s->mVetoed = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
AmendmentTableImpl::unVeto (uint256 const& amendment)
|
||||
{
|
||||
ScopedLockType sl (mLock);
|
||||
AmendmentState* s = getCreate (amendment, false);
|
||||
|
||||
if (!s || !s->mVetoed)
|
||||
return false;
|
||||
|
||||
s->mVetoed = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
AmendmentTableImpl::enable (uint256 const& amendment)
|
||||
{
|
||||
ScopedLockType sl (mLock);
|
||||
AmendmentState* s = getCreate (amendment, true);
|
||||
|
||||
if (s->mEnabled)
|
||||
return false;
|
||||
|
||||
s->mEnabled = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
AmendmentTableImpl::disable (uint256 const& amendment)
|
||||
{
|
||||
ScopedLockType sl (mLock);
|
||||
AmendmentState* s = getCreate (amendment, false);
|
||||
|
||||
if (!s || !s->mEnabled)
|
||||
return false;
|
||||
|
||||
s->mEnabled = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
AmendmentTableImpl::isEnabled (uint256 const& amendment)
|
||||
{
|
||||
ScopedLockType sl (mLock);
|
||||
AmendmentState* s = getCreate (amendment, false);
|
||||
return s && s->mEnabled;
|
||||
}
|
||||
|
||||
bool
|
||||
AmendmentTableImpl::isSupported (uint256 const& amendment)
|
||||
{
|
||||
ScopedLockType sl (mLock);
|
||||
AmendmentState* s = getCreate (amendment, false);
|
||||
return s && s->mSupported;
|
||||
}
|
||||
|
||||
AmendmentTableImpl::amendmentList_t
|
||||
AmendmentTableImpl::getVetoed ()
|
||||
{
|
||||
amendmentList_t ret;
|
||||
ScopedLockType sl (mLock);
|
||||
for (auto const& e : m_amendmentMap)
|
||||
{
|
||||
if (e.second.mVetoed)
|
||||
ret.insert (e.first);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
AmendmentTableImpl::amendmentList_t
|
||||
AmendmentTableImpl::getEnabled ()
|
||||
{
|
||||
amendmentList_t ret;
|
||||
ScopedLockType sl (mLock);
|
||||
for (auto const& e : m_amendmentMap)
|
||||
{
|
||||
if (e.second.mEnabled)
|
||||
ret.insert (e.first);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool
|
||||
AmendmentTableImpl::shouldEnable (std::uint32_t closeTime,
|
||||
const AmendmentState& fs)
|
||||
{
|
||||
if (fs.mVetoed || fs.mEnabled || !fs.mSupported || (fs.m_lastMajority != m_lastReport))
|
||||
return false;
|
||||
|
||||
if (fs.m_firstMajority == m_firstReport)
|
||||
{
|
||||
// had a majority when we first started the server, relaxed check
|
||||
// WRITEME
|
||||
}
|
||||
|
||||
// didn't have a majority when we first started the server, normal check
|
||||
return (fs.m_lastMajority - fs.m_firstMajority) > m_majorityTime.count();
|
||||
}
|
||||
|
||||
AmendmentTableImpl::amendmentList_t
|
||||
AmendmentTableImpl::getToEnable (core::Clock::time_point closeTime)
|
||||
{
|
||||
amendmentList_t ret;
|
||||
ScopedLockType sl (mLock);
|
||||
|
||||
if (m_lastReport != 0)
|
||||
{
|
||||
for (auto const& e : m_amendmentMap)
|
||||
{
|
||||
if (shouldEnable (closeTime, e.second))
|
||||
ret.insert (e.first);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
AmendmentTableImpl::amendmentList_t
|
||||
AmendmentTableImpl::getDesired ()
|
||||
{
|
||||
amendmentList_t ret;
|
||||
ScopedLockType sl (mLock);
|
||||
|
||||
for (auto const& e : m_amendmentMap)
|
||||
{
|
||||
if (e.second.mSupported && !e.second.mEnabled && !e.second.mVetoed)
|
||||
ret.insert (e.first);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
AmendmentTableImpl::reportValidations (const AmendmentSet& set)
|
||||
{
|
||||
if (set.mTrustedValidations == 0)
|
||||
return;
|
||||
|
||||
int threshold = (set.mTrustedValidations * mMajorityFraction) / 256;
|
||||
|
||||
typedef std::map<uint256, int>::value_type u256_int_pair;
|
||||
|
||||
ScopedLockType sl (mLock);
|
||||
|
||||
if (m_firstReport == 0)
|
||||
m_firstReport = set.mCloseTime;
|
||||
|
||||
std::vector<uint256> changedAmendments;
|
||||
changedAmendments.resize(set.mVotes.size());
|
||||
|
||||
for (auto const& e : set.mVotes)
|
||||
{
|
||||
AmendmentState& state = m_amendmentMap[e.first];
|
||||
if (m_journal.debug) m_journal.debug <<
|
||||
"Amendment " << to_string (e.first) <<
|
||||
" has " << e.second <<
|
||||
" votes, needs " << threshold;
|
||||
|
||||
if (e.second >= threshold)
|
||||
{
|
||||
// we have a majority
|
||||
state.m_lastMajority = set.mCloseTime;
|
||||
|
||||
if (state.m_firstMajority == 0)
|
||||
{
|
||||
if (m_journal.warning) m_journal.warning <<
|
||||
"Amendment " << to_string (e.first) <<
|
||||
" attains a majority vote";
|
||||
|
||||
state.m_firstMajority = set.mCloseTime;
|
||||
changedAmendments.push_back(e.first);
|
||||
}
|
||||
}
|
||||
else // we have no majority
|
||||
{
|
||||
if (state.m_firstMajority != 0)
|
||||
{
|
||||
if (m_journal.warning) m_journal.warning <<
|
||||
"Amendment " << to_string (e.first) <<
|
||||
" loses majority vote";
|
||||
|
||||
state.m_firstMajority = 0;
|
||||
state.m_lastMajority = 0;
|
||||
changedAmendments.push_back(e.first);
|
||||
}
|
||||
}
|
||||
}
|
||||
m_lastReport = set.mCloseTime;
|
||||
|
||||
if (!changedAmendments.empty())
|
||||
{
|
||||
DeprecatedScopedLock sl (getApp().getWalletDB ()->getDBLock ());
|
||||
Database* db = getApp().getWalletDB ()->getDB ();
|
||||
|
||||
db->executeSQL ("BEGIN TRANSACTION;");
|
||||
for (auto const& hash : changedAmendments)
|
||||
{
|
||||
AmendmentState& fState = m_amendmentMap[hash];
|
||||
db->executeSQL (boost::str (boost::format (
|
||||
"UPDATE Features SET FirstMajority = %d WHERE Hash = '%s';") %
|
||||
fState.m_firstMajority % to_string (hash)));
|
||||
db->executeSQL (boost::str (boost::format (
|
||||
"UPDATE Features SET LastMajority = %d WHERE Hash = '%s';") %
|
||||
fState.m_lastMajority % to_string(hash)));
|
||||
}
|
||||
db->executeSQL ("END TRANSACTION;");
|
||||
changedAmendments.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AmendmentTableImpl::setEnabled (const std::vector<uint256>& amendments)
|
||||
{
|
||||
ScopedLockType sl (mLock);
|
||||
for (auto& e : m_amendmentMap)
|
||||
{
|
||||
e.second.mEnabled = false;
|
||||
}
|
||||
for (auto const& e : amendments)
|
||||
{
|
||||
m_amendmentMap[e].mEnabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AmendmentTableImpl::setSupported (const std::vector<uint256>& amendments)
|
||||
{
|
||||
ScopedLockType sl (mLock);
|
||||
for (auto &e : m_amendmentMap)
|
||||
{
|
||||
e.second.mSupported = false;
|
||||
}
|
||||
for (auto const& e : amendments)
|
||||
{
|
||||
m_amendmentMap[e].mSupported = true;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AmendmentTableImpl::doValidation (Ledger::ref lastClosedLedger,
|
||||
STObject& baseValidation)
|
||||
{
|
||||
amendmentList_t lAmendments = getDesired();
|
||||
|
||||
if (lAmendments.empty())
|
||||
return;
|
||||
|
||||
STVector256 vAmendments (sfAmendments);
|
||||
for (auto const& uAmendment : lAmendments)
|
||||
{
|
||||
vAmendments.addValue (uAmendment);
|
||||
}
|
||||
vAmendments.sort ();
|
||||
baseValidation.setFieldV256 (sfAmendments, vAmendments);
|
||||
}
|
||||
|
||||
void
|
||||
AmendmentTableImpl::doVoting (Ledger::ref lastClosedLedger,
|
||||
SHAMap::ref initialPosition)
|
||||
{
|
||||
|
||||
// LCL must be flag ledger
|
||||
assert((lastClosedLedger->getLedgerSeq () % 256) == 0);
|
||||
|
||||
AmendmentSet amendmentSet (lastClosedLedger->getParentCloseTimeNC ());
|
||||
|
||||
// get validations for ledger before flag ledger
|
||||
ValidationSet valSet = getApp().getValidations ().getValidations (lastClosedLedger->getParentHash ());
|
||||
for (auto const& entry : valSet)
|
||||
{
|
||||
auto const& val = *entry.second;
|
||||
|
||||
if (val.isTrusted ())
|
||||
{
|
||||
amendmentSet.addVoter ();
|
||||
if (val.isFieldPresent (sfAmendments))
|
||||
{
|
||||
for (auto const& amendment : val.getFieldV256 (sfAmendments))
|
||||
{
|
||||
amendmentSet.addVote (amendment);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
reportValidations (amendmentSet);
|
||||
|
||||
amendmentList_t lAmendments = getToEnable (lastClosedLedger->getCloseTimeNC ());
|
||||
for (auto const& uAmendment : lAmendments)
|
||||
{
|
||||
if (m_journal.warning) m_journal.warning <<
|
||||
"Voting for amendment: " << uAmendment;
|
||||
|
||||
// Create the transaction to enable the amendment
|
||||
SerializedTransaction trans (ttAMENDMENT);
|
||||
trans.setFieldAccount (sfAccount, uint160 ());
|
||||
trans.setFieldH256 (sfAmendment, uAmendment);
|
||||
uint256 txID = trans.getTransactionID ();
|
||||
|
||||
if (m_journal.warning) m_journal.warning <<
|
||||
"Vote ID: " << txID;
|
||||
|
||||
// Inject the transaction into our initial proposal
|
||||
Serializer s;
|
||||
trans.add (s, true);
|
||||
#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 amendment transaction";
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
Json::Value
|
||||
AmendmentTableImpl::getJson (int)
|
||||
{
|
||||
Json::Value ret(Json::objectValue);
|
||||
{
|
||||
ScopedLockType sl(mLock);
|
||||
for (auto const& e : m_amendmentMap)
|
||||
{
|
||||
setJson (ret[to_string (e.first)] = Json::objectValue, e.second);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
AmendmentTableImpl::setJson (Json::Value& v, const AmendmentState& fs)
|
||||
{
|
||||
if (!fs.mFriendlyName.empty())
|
||||
v["name"] = fs.mFriendlyName;
|
||||
|
||||
v["supported"] = fs.mSupported;
|
||||
v["vetoed"] = fs.mVetoed;
|
||||
|
||||
if (fs.mEnabled)
|
||||
v["enabled"] = true;
|
||||
else
|
||||
{
|
||||
v["enabled"] = false;
|
||||
|
||||
if (m_lastReport != 0)
|
||||
{
|
||||
if (fs.m_lastMajority == 0)
|
||||
{
|
||||
v["majority"] = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fs.m_firstMajority != 0)
|
||||
{
|
||||
if (fs.m_firstMajority == m_firstReport)
|
||||
v["majority_start"] = "start";
|
||||
else
|
||||
v["majority_start"] = fs.m_firstMajority;
|
||||
}
|
||||
|
||||
if (fs.m_lastMajority != 0)
|
||||
{
|
||||
if (fs.m_lastMajority == m_lastReport)
|
||||
v["majority_until"] = "now";
|
||||
else
|
||||
v["majority_until"] = fs.m_lastMajority;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fs.mVetoed)
|
||||
v["veto"] = true;
|
||||
}
|
||||
|
||||
Json::Value
|
||||
AmendmentTableImpl::getJson (uint256 const& amendmentID)
|
||||
{
|
||||
Json::Value ret = Json::objectValue;
|
||||
Json::Value& jAmendment = (ret[to_string (amendmentID)] = Json::objectValue);
|
||||
|
||||
{
|
||||
ScopedLockType sl(mLock);
|
||||
|
||||
AmendmentState *amendmentState = getCreate (amendmentID, true);
|
||||
setJson (jAmendment, *amendmentState);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::unique_ptr<AmendmentTable>
|
||||
make_AmendmentTable (std::chrono::seconds majorityTime, int majorityFraction,
|
||||
beast::Journal journal)
|
||||
{
|
||||
return std::make_unique<AmendmentTableImpl> (majorityTime, majorityFraction,
|
||||
journal);
|
||||
}
|
||||
|
||||
} // ripple
|
||||
93
src/ripple/module/app/misc/CanonicalTXSet.cpp
Normal file
93
src/ripple/module/app/misc/CanonicalTXSet.cpp
Normal file
@@ -0,0 +1,93 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
namespace ripple {
|
||||
|
||||
bool CanonicalTXSet::Key::operator< (Key const& rhs) const
|
||||
{
|
||||
if (mAccount < rhs.mAccount) return true;
|
||||
|
||||
if (mAccount > rhs.mAccount) return false;
|
||||
|
||||
if (mSeq < rhs.mSeq) return true;
|
||||
|
||||
if (mSeq > rhs.mSeq) return false;
|
||||
|
||||
return mTXid < rhs.mTXid;
|
||||
}
|
||||
|
||||
bool CanonicalTXSet::Key::operator> (Key const& rhs) const
|
||||
{
|
||||
if (mAccount > rhs.mAccount) return true;
|
||||
|
||||
if (mAccount < rhs.mAccount) return false;
|
||||
|
||||
if (mSeq > rhs.mSeq) return true;
|
||||
|
||||
if (mSeq < rhs.mSeq) return false;
|
||||
|
||||
return mTXid > rhs.mTXid;
|
||||
}
|
||||
|
||||
bool CanonicalTXSet::Key::operator<= (Key const& rhs) const
|
||||
{
|
||||
if (mAccount < rhs.mAccount) return true;
|
||||
|
||||
if (mAccount > rhs.mAccount) return false;
|
||||
|
||||
if (mSeq < rhs.mSeq) return true;
|
||||
|
||||
if (mSeq > rhs.mSeq) return false;
|
||||
|
||||
return mTXid <= rhs.mTXid;
|
||||
}
|
||||
|
||||
bool CanonicalTXSet::Key::operator>= (Key const& rhs)const
|
||||
{
|
||||
if (mAccount > rhs.mAccount) return true;
|
||||
|
||||
if (mAccount < rhs.mAccount) return false;
|
||||
|
||||
if (mSeq > rhs.mSeq) return true;
|
||||
|
||||
if (mSeq < rhs.mSeq) return false;
|
||||
|
||||
return mTXid >= rhs.mTXid;
|
||||
}
|
||||
|
||||
void CanonicalTXSet::push_back (SerializedTransaction::ref txn)
|
||||
{
|
||||
uint256 effectiveAccount = mSetHash;
|
||||
|
||||
effectiveAccount ^= to256 (txn->getSourceAccount ().getAccountID ());
|
||||
|
||||
mMap.insert (std::make_pair (
|
||||
Key (effectiveAccount, txn->getSequence (), txn->getTransactionID ()),
|
||||
txn));
|
||||
}
|
||||
|
||||
CanonicalTXSet::iterator CanonicalTXSet::erase (iterator const& it)
|
||||
{
|
||||
iterator tmp = it;
|
||||
++tmp;
|
||||
mMap.erase (it);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
} // ripple
|
||||
126
src/ripple/module/app/misc/CanonicalTXSet.h
Normal file
126
src/ripple/module/app/misc/CanonicalTXSet.h
Normal file
@@ -0,0 +1,126 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_CANONICALTXSET_H
|
||||
#define RIPPLE_CANONICALTXSET_H
|
||||
|
||||
namespace ripple {
|
||||
|
||||
/** Holds transactions which were deferred to the next pass of consensus.
|
||||
|
||||
"Canonical" refers to the order in which transactions are applied.
|
||||
|
||||
- Puts transactions from the same account in sequence order
|
||||
|
||||
*/
|
||||
// VFALCO TODO rename to SortedTxSet
|
||||
class CanonicalTXSet : beast::LeakChecked <CanonicalTXSet>
|
||||
{
|
||||
public:
|
||||
class Key
|
||||
{
|
||||
public:
|
||||
Key (uint256 const& account, std::uint32_t seq, uint256 const& id)
|
||||
: mAccount (account)
|
||||
, mTXid (id)
|
||||
, mSeq (seq)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator< (Key const& rhs) const;
|
||||
bool operator> (Key const& rhs) const;
|
||||
bool operator<= (Key const& rhs) const;
|
||||
bool operator>= (Key const& rhs) const;
|
||||
|
||||
bool operator== (Key const& rhs) const
|
||||
{
|
||||
return mTXid == rhs.mTXid;
|
||||
}
|
||||
bool operator!= (Key const& rhs) const
|
||||
{
|
||||
return mTXid != rhs.mTXid;
|
||||
}
|
||||
|
||||
uint256 const& getTXID () const
|
||||
{
|
||||
return mTXid;
|
||||
}
|
||||
|
||||
private:
|
||||
uint256 mAccount;
|
||||
uint256 mTXid;
|
||||
std::uint32_t mSeq;
|
||||
};
|
||||
|
||||
typedef std::map <Key, SerializedTransaction::pointer>::iterator iterator;
|
||||
typedef std::map <Key, SerializedTransaction::pointer>::const_iterator const_iterator;
|
||||
|
||||
public:
|
||||
explicit CanonicalTXSet (LedgerHash const& lastClosedLedgerHash)
|
||||
: mSetHash (lastClosedLedgerHash)
|
||||
{
|
||||
}
|
||||
|
||||
void push_back (SerializedTransaction::ref txn);
|
||||
|
||||
// VFALCO TODO remove this function
|
||||
void reset (LedgerHash const& newLastClosedLedgerHash)
|
||||
{
|
||||
mSetHash = newLastClosedLedgerHash;
|
||||
|
||||
mMap.clear ();
|
||||
}
|
||||
|
||||
iterator erase (iterator const& it);
|
||||
|
||||
iterator begin ()
|
||||
{
|
||||
return mMap.begin ();
|
||||
}
|
||||
iterator end ()
|
||||
{
|
||||
return mMap.end ();
|
||||
}
|
||||
const_iterator begin () const
|
||||
{
|
||||
return mMap.begin ();
|
||||
}
|
||||
const_iterator end () const
|
||||
{
|
||||
return mMap.end ();
|
||||
}
|
||||
size_t size () const
|
||||
{
|
||||
return mMap.size ();
|
||||
}
|
||||
bool empty () const
|
||||
{
|
||||
return mMap.empty ();
|
||||
}
|
||||
|
||||
private:
|
||||
// Used to salt the accounts so people can't mine for low account numbers
|
||||
uint256 mSetHash;
|
||||
|
||||
std::map <Key, SerializedTransaction::pointer> mMap;
|
||||
};
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
62
src/ripple/module/app/misc/FeeVote.h
Normal file
62
src/ripple/module/app/misc/FeeVote.h
Normal file
@@ -0,0 +1,62 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_IFEEVOTE_H
|
||||
#define RIPPLE_IFEEVOTE_H
|
||||
|
||||
namespace ripple {
|
||||
|
||||
/** Manager to process fee votes. */
|
||||
class FeeVote
|
||||
{
|
||||
public:
|
||||
/** Create a new fee vote manager.
|
||||
|
||||
@param targetBaseFee
|
||||
@param targetReserveBase
|
||||
@param targetReserveIncrement
|
||||
@param journal
|
||||
*/
|
||||
|
||||
virtual ~FeeVote () { }
|
||||
|
||||
/** Add local fee preference to validation.
|
||||
|
||||
@param lastClosedLedger
|
||||
@param baseValidation
|
||||
*/
|
||||
virtual void doValidation (Ledger::ref lastClosedLedger,
|
||||
STObject& baseValidation) = 0;
|
||||
|
||||
/** Cast our local vote on the fee.
|
||||
|
||||
@param lastClosedLedger
|
||||
@param initialPosition
|
||||
*/
|
||||
virtual void doVoting (Ledger::ref lastClosedLedger,
|
||||
SHAMap::ref initialPosition) = 0;
|
||||
};
|
||||
|
||||
std::unique_ptr<FeeVote>
|
||||
make_FeeVote (std::uint64_t targetBaseFee, std::uint32_t targetReserveBase,
|
||||
std::uint32_t targetReserveIncrement, beast::Journal journal);
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
233
src/ripple/module/app/misc/FeeVoteImpl.cpp
Normal file
233
src/ripple/module/app/misc/FeeVoteImpl.cpp
Normal file
@@ -0,0 +1,233 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class FeaturesImpl;
|
||||
|
||||
class FeeVoteImpl : public FeeVote
|
||||
{
|
||||
private:
|
||||
|
||||
template <typename Integer>
|
||||
class VotableInteger
|
||||
{
|
||||
public:
|
||||
VotableInteger (Integer current, Integer target)
|
||||
: mCurrent (current)
|
||||
, mTarget (target)
|
||||
{
|
||||
// Add our vote
|
||||
++mVoteMap[mTarget];
|
||||
}
|
||||
|
||||
bool
|
||||
mayVote () const
|
||||
{
|
||||
// If we love the current setting, we will not vote
|
||||
return mCurrent != mTarget;
|
||||
}
|
||||
|
||||
void
|
||||
addVote (Integer vote)
|
||||
{
|
||||
++mVoteMap[vote];
|
||||
}
|
||||
|
||||
void
|
||||
noVote ()
|
||||
{
|
||||
addVote (mCurrent);
|
||||
}
|
||||
|
||||
Integer
|
||||
getVotes ()
|
||||
{
|
||||
Integer ourVote = mCurrent;
|
||||
int weight = 0;
|
||||
|
||||
typedef typename std::map<Integer, int>::value_type mapVType;
|
||||
for (auto const& e : mVoteMap)
|
||||
{
|
||||
// Take most voted value between current and target, inclusive
|
||||
if ((e.first <= std::max (mTarget, mCurrent)) &&
|
||||
(e.first >= std::min (mTarget, mCurrent)) &&
|
||||
(e.second > weight))
|
||||
{
|
||||
ourVote = e.first;
|
||||
weight = e.second;
|
||||
}
|
||||
}
|
||||
|
||||
return ourVote;
|
||||
}
|
||||
|
||||
private:
|
||||
Integer mCurrent; // The current setting
|
||||
Integer mTarget; // The setting we want
|
||||
std::map<Integer, int> mVoteMap;
|
||||
};
|
||||
|
||||
public:
|
||||
FeeVoteImpl (std::uint64_t targetBaseFee, std::uint32_t targetReserveBase,
|
||||
std::uint32_t targetReserveIncrement, beast::Journal journal)
|
||||
: mTargetBaseFee (targetBaseFee)
|
||||
, mTargetReserveBase (targetReserveBase)
|
||||
, mTargetReserveIncrement (targetReserveIncrement)
|
||||
, m_journal (journal)
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
doValidation (Ledger::ref lastClosedLedger, STObject& baseValidation) override
|
||||
{
|
||||
if (lastClosedLedger->getBaseFee () != mTargetBaseFee)
|
||||
{
|
||||
if (m_journal.info) m_journal.info <<
|
||||
"Voting for base fee of " << mTargetBaseFee;
|
||||
|
||||
baseValidation.setFieldU64 (sfBaseFee, mTargetBaseFee);
|
||||
}
|
||||
|
||||
if (lastClosedLedger->getReserve (0) != mTargetReserveBase)
|
||||
{
|
||||
if (m_journal.info) m_journal.info <<
|
||||
"Voting for base resrve of " << mTargetReserveBase;
|
||||
|
||||
baseValidation.setFieldU32(sfReserveBase, mTargetReserveBase);
|
||||
}
|
||||
|
||||
if (lastClosedLedger->getReserveInc () != mTargetReserveIncrement)
|
||||
{
|
||||
if (m_journal.info) m_journal.info <<
|
||||
"Voting for reserve increment of " << mTargetReserveIncrement;
|
||||
|
||||
baseValidation.setFieldU32 (sfReserveIncrement, mTargetReserveIncrement);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
doVoting (Ledger::ref lastClosedLedger, SHAMap::ref initialPosition) override
|
||||
{
|
||||
// LCL must be flag ledger
|
||||
assert ((lastClosedLedger->getLedgerSeq () % 256) == 0);
|
||||
|
||||
VotableInteger<std::uint64_t> baseFeeVote (lastClosedLedger->getBaseFee (), mTargetBaseFee);
|
||||
VotableInteger<std::uint32_t> baseReserveVote (lastClosedLedger->getReserve (0), mTargetReserveBase);
|
||||
VotableInteger<std::uint32_t> incReserveVote (lastClosedLedger->getReserveInc (), mTargetReserveIncrement);
|
||||
|
||||
// get validations for ledger before flag
|
||||
ValidationSet set = getApp().getValidations ().getValidations (lastClosedLedger->getParentHash ());
|
||||
for (auto const& e : set)
|
||||
{
|
||||
SerializedValidation const& val = *e.second;
|
||||
|
||||
if (val.isTrusted ())
|
||||
{
|
||||
if (val.isFieldPresent (sfBaseFee))
|
||||
{
|
||||
baseFeeVote.addVote (val.getFieldU64 (sfBaseFee));
|
||||
}
|
||||
else
|
||||
{
|
||||
baseFeeVote.noVote ();
|
||||
}
|
||||
|
||||
if (val.isFieldPresent (sfReserveBase))
|
||||
{
|
||||
baseReserveVote.addVote (val.getFieldU32 (sfReserveBase));
|
||||
}
|
||||
else
|
||||
{
|
||||
baseReserveVote.noVote ();
|
||||
}
|
||||
|
||||
if (val.isFieldPresent (sfReserveIncrement))
|
||||
{
|
||||
incReserveVote.addVote (val.getFieldU32 (sfReserveIncrement));
|
||||
}
|
||||
else
|
||||
{
|
||||
incReserveVote.noVote ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// choose our positions
|
||||
std::uint64_t baseFee = baseFeeVote.getVotes ();
|
||||
std::uint32_t baseReserve = baseReserveVote.getVotes ();
|
||||
std::uint32_t incReserve = incReserveVote.getVotes ();
|
||||
|
||||
// add transactions to our position
|
||||
if ((baseFee != lastClosedLedger->getBaseFee ()) ||
|
||||
(baseReserve != lastClosedLedger->getReserve (0)) ||
|
||||
(incReserve != lastClosedLedger->getReserveInc ()))
|
||||
{
|
||||
if (m_journal.warning) m_journal.warning <<
|
||||
"We are voting for a fee change: " << baseFee <<
|
||||
"/" << baseReserve <<
|
||||
"/" << incReserve;
|
||||
|
||||
SerializedTransaction trans (ttFEE);
|
||||
trans.setFieldAccount (sfAccount, uint160 ());
|
||||
trans.setFieldU64 (sfBaseFee, baseFee);
|
||||
trans.setFieldU32 (sfReferenceFeeUnits, 10);
|
||||
trans.setFieldU32 (sfReserveBase, baseReserve);
|
||||
trans.setFieldU32 (sfReserveIncrement, incReserve);
|
||||
|
||||
uint256 txID = trans.getTransactionID ();
|
||||
|
||||
if (m_journal.warning) m_journal.warning <<
|
||||
"Vote: " << txID;
|
||||
|
||||
Serializer s;
|
||||
trans.add (s, true);
|
||||
|
||||
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 fee change";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::uint64_t mTargetBaseFee;
|
||||
std::uint32_t mTargetReserveBase;
|
||||
std::uint32_t mTargetReserveIncrement;
|
||||
beast::Journal m_journal;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
std::unique_ptr<FeeVote>
|
||||
make_FeeVote (std::uint64_t targetBaseFee, std::uint32_t targetReserveBase,
|
||||
std::uint32_t targetReserveIncrement, beast::Journal journal)
|
||||
{
|
||||
return std::make_unique<FeeVoteImpl> (targetBaseFee, targetReserveBase,
|
||||
targetReserveIncrement, journal);
|
||||
}
|
||||
|
||||
} // ripple
|
||||
246
src/ripple/module/app/misc/HashRouter.cpp
Normal file
246
src/ripple/module/app/misc/HashRouter.cpp
Normal file
@@ -0,0 +1,246 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
namespace ripple {
|
||||
|
||||
// VFALCO TODO Inline the function definitions
|
||||
class HashRouter : public IHashRouter
|
||||
{
|
||||
private:
|
||||
/** An entry in the routing table.
|
||||
*/
|
||||
class Entry : public CountedObject <Entry>
|
||||
{
|
||||
public:
|
||||
static char const* getCountedObjectName () { return "HashRouterEntry"; }
|
||||
|
||||
Entry ()
|
||||
: mFlags (0)
|
||||
{
|
||||
}
|
||||
|
||||
std::set <PeerShortID> const& peekPeers () const
|
||||
{
|
||||
return mPeers;
|
||||
}
|
||||
|
||||
void addPeer (PeerShortID peer)
|
||||
{
|
||||
if (peer != 0)
|
||||
mPeers.insert (peer);
|
||||
}
|
||||
|
||||
bool hasPeer (PeerShortID peer) const
|
||||
{
|
||||
return mPeers.count (peer) > 0;
|
||||
}
|
||||
|
||||
int getFlags (void) const
|
||||
{
|
||||
return mFlags;
|
||||
}
|
||||
|
||||
bool hasFlag (int mask) const
|
||||
{
|
||||
return (mFlags & mask) != 0;
|
||||
}
|
||||
|
||||
void setFlag (int flagsToSet)
|
||||
{
|
||||
mFlags |= flagsToSet;
|
||||
}
|
||||
|
||||
void clearFlag (int flagsToClear)
|
||||
{
|
||||
mFlags &= ~flagsToClear;
|
||||
}
|
||||
|
||||
void swapSet (std::set <PeerShortID>& other)
|
||||
{
|
||||
mPeers.swap (other);
|
||||
}
|
||||
|
||||
private:
|
||||
int mFlags;
|
||||
std::set <PeerShortID> mPeers;
|
||||
};
|
||||
|
||||
public:
|
||||
explicit HashRouter (int holdTime)
|
||||
: mHoldTime (holdTime)
|
||||
{
|
||||
}
|
||||
|
||||
bool addSuppression (uint256 const& index);
|
||||
|
||||
bool addSuppressionPeer (uint256 const& index, PeerShortID peer);
|
||||
bool addSuppressionPeer (uint256 const& index, PeerShortID peer, int& flags);
|
||||
bool addSuppressionFlags (uint256 const& index, int flag);
|
||||
bool setFlag (uint256 const& index, int flag);
|
||||
int getFlags (uint256 const& index);
|
||||
|
||||
bool swapSet (uint256 const& index, std::set<PeerShortID>& peers, int flag);
|
||||
|
||||
private:
|
||||
Entry getEntry (uint256 const& );
|
||||
|
||||
Entry& findCreateEntry (uint256 const& , bool& created);
|
||||
|
||||
typedef RippleMutex LockType;
|
||||
typedef std::lock_guard <LockType> ScopedLockType;
|
||||
LockType mLock;
|
||||
|
||||
// Stores all suppressed hashes and their expiration time
|
||||
ripple::unordered_map <uint256, Entry> mSuppressionMap;
|
||||
|
||||
// Stores all expiration times and the hashes indexed for them
|
||||
std::map< int, std::list<uint256> > mSuppressionTimes;
|
||||
|
||||
int mHoldTime;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
HashRouter::Entry& HashRouter::findCreateEntry (uint256 const& index, bool& created)
|
||||
{
|
||||
ripple::unordered_map<uint256, Entry>::iterator fit = mSuppressionMap.find (index);
|
||||
|
||||
if (fit != mSuppressionMap.end ())
|
||||
{
|
||||
created = false;
|
||||
return fit->second;
|
||||
}
|
||||
|
||||
created = true;
|
||||
|
||||
int now = UptimeTimer::getInstance ().getElapsedSeconds ();
|
||||
int expireTime = now - mHoldTime;
|
||||
|
||||
// See if any supressions need to be expired
|
||||
std::map< int, std::list<uint256> >::iterator it = mSuppressionTimes.begin ();
|
||||
|
||||
if ((it != mSuppressionTimes.end ()) && (it->first <= expireTime))
|
||||
{
|
||||
BOOST_FOREACH (uint256 const & lit, it->second)
|
||||
mSuppressionMap.erase (lit);
|
||||
mSuppressionTimes.erase (it);
|
||||
}
|
||||
|
||||
mSuppressionTimes[now].push_back (index);
|
||||
return mSuppressionMap.emplace (index, Entry ()).first->second;
|
||||
}
|
||||
|
||||
bool HashRouter::addSuppression (uint256 const& index)
|
||||
{
|
||||
ScopedLockType sl (mLock);
|
||||
|
||||
bool created;
|
||||
findCreateEntry (index, created);
|
||||
return created;
|
||||
}
|
||||
|
||||
HashRouter::Entry HashRouter::getEntry (uint256 const& index)
|
||||
{
|
||||
ScopedLockType sl (mLock);
|
||||
|
||||
bool created;
|
||||
return findCreateEntry (index, created);
|
||||
}
|
||||
|
||||
bool HashRouter::addSuppressionPeer (uint256 const& index, PeerShortID peer)
|
||||
{
|
||||
ScopedLockType sl (mLock);
|
||||
|
||||
bool created;
|
||||
findCreateEntry (index, created).addPeer (peer);
|
||||
return created;
|
||||
}
|
||||
|
||||
bool HashRouter::addSuppressionPeer (uint256 const& index, PeerShortID peer, int& flags)
|
||||
{
|
||||
ScopedLockType sl (mLock);
|
||||
|
||||
bool created;
|
||||
Entry& s = findCreateEntry (index, created);
|
||||
s.addPeer (peer);
|
||||
flags = s.getFlags ();
|
||||
return created;
|
||||
}
|
||||
|
||||
int HashRouter::getFlags (uint256 const& index)
|
||||
{
|
||||
ScopedLockType sl (mLock);
|
||||
|
||||
bool created;
|
||||
return findCreateEntry (index, created).getFlags ();
|
||||
}
|
||||
|
||||
bool HashRouter::addSuppressionFlags (uint256 const& index, int flag)
|
||||
{
|
||||
ScopedLockType sl (mLock);
|
||||
|
||||
bool created;
|
||||
findCreateEntry (index, created).setFlag (flag);
|
||||
return created;
|
||||
}
|
||||
|
||||
bool HashRouter::setFlag (uint256 const& index, int flag)
|
||||
{
|
||||
// VFALCO NOTE Comments like this belong in the HEADER file,
|
||||
// and more importantly in a Javadoc comment so
|
||||
// they appear in the generated documentation.
|
||||
//
|
||||
// return: true = changed, false = unchanged
|
||||
assert (flag != 0);
|
||||
|
||||
ScopedLockType sl (mLock);
|
||||
|
||||
bool created;
|
||||
Entry& s = findCreateEntry (index, created);
|
||||
|
||||
if ((s.getFlags () & flag) == flag)
|
||||
return false;
|
||||
|
||||
s.setFlag (flag);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HashRouter::swapSet (uint256 const& index, std::set<PeerShortID>& peers, int flag)
|
||||
{
|
||||
ScopedLockType sl (mLock);
|
||||
|
||||
bool created;
|
||||
Entry& s = findCreateEntry (index, created);
|
||||
|
||||
if ((s.getFlags () & flag) == flag)
|
||||
return false;
|
||||
|
||||
s.swapSet (peers);
|
||||
s.setFlag (flag);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
IHashRouter* IHashRouter::New (int holdTime)
|
||||
{
|
||||
return new HashRouter (holdTime);
|
||||
}
|
||||
|
||||
} // ripple
|
||||
|
||||
87
src/ripple/module/app/misc/IHashRouter.h
Normal file
87
src/ripple/module/app/misc/IHashRouter.h
Normal file
@@ -0,0 +1,87 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_HASHROUTER_H_INCLUDED
|
||||
#define RIPPLE_HASHROUTER_H_INCLUDED
|
||||
|
||||
namespace ripple {
|
||||
|
||||
// VFALCO NOTE Are these the flags?? Why aren't we using a packed struct?
|
||||
// VFALCO TODO convert these macros to int constants
|
||||
#define SF_RELAYED 0x01 // Has already been relayed to other nodes
|
||||
// VFALCO NOTE How can both bad and good be set on a hash?
|
||||
#define SF_BAD 0x02 // Signature/format is bad
|
||||
#define SF_SIGGOOD 0x04 // Signature is good
|
||||
#define SF_SAVED 0x08
|
||||
#define SF_RETRY 0x10 // Transaction can be retried
|
||||
#define SF_TRUSTED 0x20 // comes from trusted source
|
||||
|
||||
/** Routing table for objects identified by hash.
|
||||
|
||||
This table keeps track of which hashes have been received by which peers.
|
||||
It is used to manage the routing and broadcasting of messages in the peer
|
||||
to peer overlay.
|
||||
*/
|
||||
class IHashRouter
|
||||
{
|
||||
public:
|
||||
// The type here *MUST* match the type of Peer::ShortId
|
||||
typedef std::uint32_t PeerShortID;
|
||||
|
||||
// VFALCO NOTE this preferred alternative to default parameters makes
|
||||
// behavior clear.
|
||||
//
|
||||
static inline int getDefaultHoldTime ()
|
||||
{
|
||||
return 300;
|
||||
}
|
||||
|
||||
// VFALCO TODO rename the parameter to entryHoldTimeInSeconds
|
||||
static IHashRouter* New (int holdTime);
|
||||
|
||||
virtual ~IHashRouter () { }
|
||||
|
||||
// VFALCO TODO Replace "Supression" terminology with something more semantically meaningful.
|
||||
virtual bool addSuppression (uint256 const& index) = 0;
|
||||
|
||||
virtual bool addSuppressionPeer (uint256 const& index, PeerShortID peer) = 0;
|
||||
|
||||
virtual bool addSuppressionPeer (uint256 const& index, PeerShortID peer, int& flags) = 0;
|
||||
|
||||
virtual bool addSuppressionFlags (uint256 const& index, int flag) = 0;
|
||||
|
||||
/** Set the flags on a hash.
|
||||
|
||||
@return `true` if the flags were changed.
|
||||
*/
|
||||
// VFALCO TODO Rename to setFlags since it works with multiple flags.
|
||||
virtual bool setFlag (uint256 const& index, int mask) = 0;
|
||||
|
||||
virtual int getFlags (uint256 const& index) = 0;
|
||||
|
||||
virtual bool swapSet (uint256 const& index, std::set<PeerShortID>& peers, int flag) = 0;
|
||||
|
||||
// VFALCO TODO This appears to be unused!
|
||||
//
|
||||
// virtual Entry getEntry (uint256 const&) = 0;
|
||||
};
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
3390
src/ripple/module/app/misc/NetworkOPs.cpp
Normal file
3390
src/ripple/module/app/misc/NetworkOPs.cpp
Normal file
File diff suppressed because it is too large
Load Diff
322
src/ripple/module/app/misc/NetworkOPs.h
Normal file
322
src/ripple/module/app/misc/NetworkOPs.h
Normal file
@@ -0,0 +1,322 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_NETWORKOPS_H
|
||||
#define RIPPLE_NETWORKOPS_H
|
||||
|
||||
#include <tuple>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
// Operations that clients may wish to perform against the network
|
||||
// Master operational handler, server sequencer, network tracker
|
||||
|
||||
class Peer;
|
||||
class LedgerConsensus;
|
||||
|
||||
// This is the primary interface into the "client" portion of the program.
|
||||
// Code that wants to do normal operations on the network such as
|
||||
// creating and monitoring accounts, creating transactions, and so on
|
||||
// should use this interface. The RPC code will primarily be a light wrapper
|
||||
// over this code.
|
||||
//
|
||||
// Eventually, it will check the node's operating mode (synched, unsynched,
|
||||
// etectera) and defer to the correct means of processing. The current
|
||||
// code assumes this node is synched (and will continue to do so until
|
||||
// there's a functional network.
|
||||
//
|
||||
/** Provides server functionality for clients.
|
||||
|
||||
Clients include backend applications, local commands, and connected
|
||||
clients. This class acts as a proxy, fulfilling the command with local
|
||||
data if possible, or asking the network and returning the results if
|
||||
needed.
|
||||
|
||||
A backend application or local client can trust a local instance of
|
||||
rippled / NetworkOPs. However, client software connecting to non-local
|
||||
instances of rippled will need to be hardened to protect against hostile
|
||||
or unreliable servers.
|
||||
*/
|
||||
class NetworkOPs
|
||||
: public InfoSub::Source
|
||||
{
|
||||
protected:
|
||||
explicit NetworkOPs (Stoppable& parent);
|
||||
|
||||
public:
|
||||
typedef beast::abstract_clock <std::chrono::seconds> clock_type;
|
||||
|
||||
enum Fault
|
||||
{
|
||||
// exceptions these functions can throw
|
||||
IO_ERROR = 1,
|
||||
NO_NETWORK = 2,
|
||||
};
|
||||
|
||||
enum OperatingMode
|
||||
{
|
||||
// how we process transactions or account balance requests
|
||||
omDISCONNECTED = 0, // not ready to process requests
|
||||
omCONNECTED = 1, // convinced we are talking to the network
|
||||
omSYNCING = 2, // fallen slightly behind
|
||||
omTRACKING = 3, // convinced we agree with the network
|
||||
omFULL = 4 // we have the ledger and can even validate
|
||||
};
|
||||
|
||||
// VFALCO TODO Fix OrderBookDB to not need this unrelated type.
|
||||
//
|
||||
typedef ripple::unordered_map <std::uint64_t, InfoSub::wptr> SubMapType;
|
||||
|
||||
public:
|
||||
// VFALCO TODO Make LedgerMaster a SharedPtr or a reference.
|
||||
//
|
||||
static NetworkOPs* New (clock_type& clock, LedgerMaster& ledgerMaster,
|
||||
Stoppable& parent, beast::Journal journal);
|
||||
|
||||
virtual ~NetworkOPs () = 0;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// Network information
|
||||
//
|
||||
|
||||
// Our best estimate of wall time in seconds from 1/1/2000
|
||||
virtual std::uint32_t getNetworkTimeNC () = 0;
|
||||
// Our best estimate of current ledger close time
|
||||
virtual std::uint32_t getCloseTimeNC () = 0;
|
||||
// Use *only* to timestamp our own validation
|
||||
virtual std::uint32_t getValidationTimeNC () = 0;
|
||||
virtual void closeTimeOffset (int) = 0;
|
||||
virtual boost::posix_time::ptime getNetworkTimePT () = 0;
|
||||
virtual std::uint32_t getLedgerID (uint256 const& hash) = 0;
|
||||
virtual std::uint32_t getCurrentLedgerID () = 0;
|
||||
|
||||
virtual OperatingMode getOperatingMode () = 0;
|
||||
virtual std::string strOperatingMode () = 0;
|
||||
virtual Ledger::pointer getClosedLedger () = 0;
|
||||
virtual Ledger::pointer getValidatedLedger () = 0;
|
||||
virtual Ledger::pointer getPublishedLedger () = 0;
|
||||
virtual Ledger::pointer getCurrentLedger () = 0;
|
||||
virtual Ledger::pointer getLedgerByHash (uint256 const& hash) = 0;
|
||||
virtual Ledger::pointer getLedgerBySeq (const std::uint32_t seq) = 0;
|
||||
virtual void missingNodeInLedger (const std::uint32_t seq) = 0;
|
||||
|
||||
virtual uint256 getClosedLedgerHash () = 0;
|
||||
|
||||
// Do we have this inclusive range of ledgers in our database
|
||||
virtual bool haveLedgerRange (std::uint32_t from, std::uint32_t to) = 0;
|
||||
virtual bool haveLedger (std::uint32_t seq) = 0;
|
||||
virtual std::uint32_t getValidatedSeq () = 0;
|
||||
virtual bool isValidated (std::uint32_t seq) = 0;
|
||||
virtual bool isValidated (std::uint32_t seq, uint256 const& hash) = 0;
|
||||
virtual bool isValidated (Ledger::ref l) = 0;
|
||||
virtual bool getValidatedRange (std::uint32_t& minVal, std::uint32_t& maxVal) = 0;
|
||||
virtual bool getFullValidatedRange (std::uint32_t& minVal, std::uint32_t& maxVal) = 0;
|
||||
|
||||
virtual SerializedValidation::ref getLastValidation () = 0;
|
||||
virtual void setLastValidation (SerializedValidation::ref v) = 0;
|
||||
virtual SLE::pointer getSLE (Ledger::pointer lpLedger, uint256 const& uHash) = 0;
|
||||
virtual SLE::pointer getSLEi (Ledger::pointer lpLedger, uint256 const& uHash) = 0;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// Transaction processing
|
||||
//
|
||||
|
||||
// must complete immediately
|
||||
// VFALCO TODO Make this a TxCallback structure
|
||||
typedef std::function<void (Transaction::pointer, TER)> stCallback;
|
||||
virtual void submitTransaction (Job&, SerializedTransaction::pointer,
|
||||
stCallback callback = stCallback ()) = 0;
|
||||
virtual Transaction::pointer submitTransactionSync (Transaction::ref tpTrans,
|
||||
bool bAdmin, bool bLocal, bool bFailHard, bool bSubmit) = 0;
|
||||
virtual void runTransactionQueue () = 0;
|
||||
virtual Transaction::pointer processTransactionCb (Transaction::pointer,
|
||||
bool bAdmin, bool bLocal, bool bFailHard, stCallback) = 0;
|
||||
virtual Transaction::pointer processTransaction (Transaction::pointer transaction,
|
||||
bool bAdmin, bool bLocal, bool bFailHard) = 0;
|
||||
virtual Transaction::pointer findTransactionByID (uint256 const& transactionID) = 0;
|
||||
virtual int findTransactionsByDestination (std::list<Transaction::pointer>&,
|
||||
const RippleAddress& destinationAccount, std::uint32_t startLedgerSeq,
|
||||
std::uint32_t endLedgerSeq, int maxTransactions) = 0;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// Account functions
|
||||
//
|
||||
|
||||
virtual AccountState::pointer getAccountState (Ledger::ref lrLedger,
|
||||
const RippleAddress& accountID) = 0;
|
||||
virtual SLE::pointer getGenerator (Ledger::ref lrLedger,
|
||||
uint160 const& uGeneratorID) = 0;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// Directory functions
|
||||
//
|
||||
|
||||
virtual STVector256 getDirNodeInfo (Ledger::ref lrLedger,
|
||||
uint256 const& uRootIndex, std::uint64_t& uNodePrevious,
|
||||
std::uint64_t& uNodeNext) = 0;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// Owner functions
|
||||
//
|
||||
|
||||
virtual Json::Value getOwnerInfo (Ledger::pointer lpLedger,
|
||||
const RippleAddress& naAccount) = 0;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// Book functions
|
||||
//
|
||||
|
||||
virtual void getBookPage (
|
||||
Ledger::pointer lpLedger,
|
||||
const uint160& uTakerPaysCurrencyID,
|
||||
const uint160& uTakerPaysIssuerID,
|
||||
const uint160& uTakerGetsCurrencyID,
|
||||
const uint160& uTakerGetsIssuerID,
|
||||
const uint160& uTakerID,
|
||||
const bool bProof,
|
||||
const unsigned int iLimit,
|
||||
const Json::Value& jvMarker,
|
||||
Json::Value& jvResult) = 0;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
// ledger proposal/close functions
|
||||
virtual void processTrustedProposal (LedgerProposal::pointer proposal,
|
||||
boost::shared_ptr<protocol::TMProposeSet> set, RippleAddress nodePublic,
|
||||
uint256 checkLedger, bool sigGood) = 0;
|
||||
|
||||
virtual SHAMapAddNode gotTXData (const boost::shared_ptr<Peer>& peer,
|
||||
uint256 const& hash, const std::list<SHAMapNode>& nodeIDs,
|
||||
const std::list< Blob >& nodeData) = 0;
|
||||
|
||||
virtual bool recvValidation (SerializedValidation::ref val,
|
||||
const std::string& source) = 0;
|
||||
|
||||
virtual void takePosition (int seq, SHAMap::ref position) = 0;
|
||||
|
||||
virtual SHAMap::pointer getTXMap (uint256 const& hash) = 0;
|
||||
|
||||
virtual bool hasTXSet (const boost::shared_ptr<Peer>& peer,
|
||||
uint256 const& set, protocol::TxSetStatus status) = 0;
|
||||
|
||||
virtual void mapComplete (uint256 const& hash, SHAMap::ref map) = 0;
|
||||
|
||||
virtual bool stillNeedTXSet (uint256 const& hash) = 0;
|
||||
|
||||
// Fetch packs
|
||||
virtual void makeFetchPack (Job&, boost::weak_ptr<Peer> peer,
|
||||
boost::shared_ptr<protocol::TMGetObjectByHash> request,
|
||||
uint256 wantLedger, std::uint32_t uUptime) = 0;
|
||||
|
||||
virtual bool shouldFetchPack (std::uint32_t seq) = 0;
|
||||
virtual void gotFetchPack (bool progress, std::uint32_t seq) = 0;
|
||||
virtual void addFetchPack (uint256 const& hash, boost::shared_ptr< Blob >& data) = 0;
|
||||
virtual bool getFetchPack (uint256 const& hash, Blob& data) = 0;
|
||||
virtual int getFetchSize () = 0;
|
||||
virtual void sweepFetchPack () = 0;
|
||||
|
||||
// network state machine
|
||||
virtual void endConsensus (bool correctLCL) = 0;
|
||||
virtual void setStandAlone () = 0;
|
||||
virtual void setStateTimer () = 0;
|
||||
|
||||
virtual void newLCL (int proposers, int convergeTime, uint256 const& ledgerHash) = 0;
|
||||
// VFALCO TODO rename to setNeedNetworkLedger
|
||||
virtual void needNetworkLedger () = 0;
|
||||
virtual void clearNeedNetworkLedger () = 0;
|
||||
virtual bool isNeedNetworkLedger () = 0;
|
||||
virtual bool isFull () = 0;
|
||||
virtual void setProposing (bool isProposing, bool isValidating) = 0;
|
||||
virtual bool isProposing () = 0;
|
||||
virtual bool isValidating () = 0;
|
||||
virtual bool isAmendmentBlocked () = 0;
|
||||
virtual void setAmendmentBlocked () = 0;
|
||||
virtual void consensusViewChange () = 0;
|
||||
virtual int getPreviousProposers () = 0;
|
||||
virtual int getPreviousConvergeTime () = 0;
|
||||
virtual std::uint32_t getLastCloseTime () = 0;
|
||||
virtual void setLastCloseTime (std::uint32_t t) = 0;
|
||||
|
||||
virtual Json::Value getConsensusInfo () = 0;
|
||||
virtual Json::Value getServerInfo (bool human, bool admin) = 0;
|
||||
virtual void clearLedgerFetch () = 0;
|
||||
virtual Json::Value getLedgerFetchInfo () = 0;
|
||||
virtual std::uint32_t acceptLedger () = 0;
|
||||
|
||||
typedef ripple::unordered_map <uint160, std::list<LedgerProposal::pointer> > Proposals;
|
||||
virtual Proposals& peekStoredProposals () = 0;
|
||||
|
||||
virtual void storeProposal (LedgerProposal::ref proposal,
|
||||
const RippleAddress& peerPublic) = 0;
|
||||
|
||||
virtual uint256 getConsensusLCL () = 0;
|
||||
|
||||
virtual void reportFeeChange () = 0;
|
||||
|
||||
virtual void updateLocalTx (Ledger::ref newValidLedger) = 0;
|
||||
virtual void addLocalTx (Ledger::ref openLedger, SerializedTransaction::ref txn) = 0;
|
||||
virtual std::size_t getLocalTxCount () = 0;
|
||||
|
||||
//Helper function to generate SQL query to get transactions
|
||||
virtual std::string transactionsSQL (std::string selection,
|
||||
const RippleAddress& account, std::int32_t minLedger, std::int32_t maxLedger,
|
||||
bool descending, std::uint32_t offset, int limit, bool binary,
|
||||
bool count, bool bAdmin) = 0;
|
||||
|
||||
// client information retrieval functions
|
||||
typedef std::vector< std::pair<Transaction::pointer, TransactionMetaSet::pointer> > AccountTxs;
|
||||
virtual AccountTxs getAccountTxs (const RippleAddress& account,
|
||||
std::int32_t minLedger, std::int32_t maxLedger, bool descending, std::uint32_t offset,
|
||||
int limit, bool bAdmin) = 0;
|
||||
|
||||
typedef std::vector< std::pair<Transaction::pointer, TransactionMetaSet::pointer> > TxsAccount;
|
||||
virtual TxsAccount getTxsAccount (const RippleAddress& account,
|
||||
std::int32_t minLedger, std::int32_t maxLedger, bool forward, Json::Value& token,
|
||||
int limit, bool bAdmin) = 0;
|
||||
|
||||
typedef std::tuple<std::string, std::string, std::uint32_t> txnMetaLedgerType;
|
||||
typedef std::vector<txnMetaLedgerType> MetaTxsList;
|
||||
virtual MetaTxsList getAccountTxsB (const RippleAddress& account,
|
||||
std::int32_t minLedger, std::int32_t maxLedger, bool descending,
|
||||
std::uint32_t offset, int limit, bool bAdmin) = 0;
|
||||
|
||||
virtual MetaTxsList getTxsAccountB (const RippleAddress& account,
|
||||
std::int32_t minLedger, std::int32_t maxLedger, bool forward,
|
||||
Json::Value& token, int limit, bool bAdmin) = 0;
|
||||
|
||||
virtual std::vector<RippleAddress> getLedgerAffectedAccounts (std::uint32_t ledgerSeq) = 0;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// Monitoring: publisher side
|
||||
//
|
||||
virtual void pubLedger (Ledger::ref lpAccepted) = 0;
|
||||
virtual void pubProposedTransaction (Ledger::ref lpCurrent,
|
||||
SerializedTransaction::ref stTxn, TER terResult) = 0;
|
||||
};
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
50
src/ripple/module/app/misc/NicknameState.cpp
Normal file
50
src/ripple/module/app/misc/NicknameState.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
namespace ripple {
|
||||
|
||||
NicknameState::NicknameState (SerializedLedgerEntry::pointer ledgerEntry) :
|
||||
mLedgerEntry (ledgerEntry)
|
||||
{
|
||||
if (!mLedgerEntry || mLedgerEntry->getType () != ltNICKNAME) return;
|
||||
}
|
||||
|
||||
bool NicknameState::haveMinimumOffer () const
|
||||
{
|
||||
return mLedgerEntry->isFieldPresent (sfMinimumOffer);
|
||||
}
|
||||
|
||||
STAmount NicknameState::getMinimumOffer () const
|
||||
{
|
||||
return mLedgerEntry->isFieldPresent (sfMinimumOffer)
|
||||
? mLedgerEntry->getFieldAmount (sfMinimumOffer)
|
||||
: STAmount ();
|
||||
}
|
||||
|
||||
RippleAddress NicknameState::getAccountID () const
|
||||
{
|
||||
return mLedgerEntry->getFieldAccount (sfAccount);
|
||||
}
|
||||
|
||||
void NicknameState::addJson (Json::Value& val)
|
||||
{
|
||||
val = mLedgerEntry->getJson (0);
|
||||
}
|
||||
|
||||
} // ripple
|
||||
64
src/ripple/module/app/misc/NicknameState.h
Normal file
64
src/ripple/module/app/misc/NicknameState.h
Normal file
@@ -0,0 +1,64 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_NICKNAMESTATE_H
|
||||
#define RIPPLE_NICKNAMESTATE_H
|
||||
|
||||
namespace ripple {
|
||||
|
||||
//
|
||||
// State of a nickname node.
|
||||
// - Isolate ledger entry format.
|
||||
//
|
||||
|
||||
class NicknameState
|
||||
{
|
||||
public:
|
||||
typedef boost::shared_ptr <NicknameState> pointer;
|
||||
|
||||
public:
|
||||
explicit NicknameState (SerializedLedgerEntry::pointer ledgerEntry); // For accounts in a ledger
|
||||
|
||||
bool haveMinimumOffer () const;
|
||||
STAmount getMinimumOffer () const;
|
||||
RippleAddress getAccountID () const;
|
||||
|
||||
SerializedLedgerEntry::pointer getSLE ()
|
||||
{
|
||||
return mLedgerEntry;
|
||||
}
|
||||
const SerializedLedgerEntry& peekSLE () const
|
||||
{
|
||||
return *mLedgerEntry;
|
||||
}
|
||||
SerializedLedgerEntry& peekSLE ()
|
||||
{
|
||||
return *mLedgerEntry;
|
||||
}
|
||||
|
||||
Blob getRaw () const;
|
||||
void addJson (Json::Value& value);
|
||||
|
||||
private:
|
||||
SerializedLedgerEntry::pointer mLedgerEntry;
|
||||
};
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
48
src/ripple/module/app/misc/Offer.cpp
Normal file
48
src/ripple/module/app/misc/Offer.cpp
Normal file
@@ -0,0 +1,48 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
namespace ripple {
|
||||
|
||||
AccountItem::pointer Offer::makeItem (const uint160& , SerializedLedgerEntry::ref ledgerEntry)
|
||||
{
|
||||
if (!ledgerEntry || ledgerEntry->getType () != ltOFFER) return (AccountItem::pointer ());
|
||||
|
||||
Offer* offer = new Offer (ledgerEntry);
|
||||
return (AccountItem::pointer (offer));
|
||||
}
|
||||
|
||||
Offer::Offer (SerializedLedgerEntry::pointer ledgerEntry) : AccountItem (ledgerEntry),
|
||||
mAccount (mLedgerEntry->getFieldAccount (sfAccount)),
|
||||
mTakerGets (mLedgerEntry->getFieldAmount (sfTakerGets)),
|
||||
mTakerPays (mLedgerEntry->getFieldAmount (sfTakerPays)),
|
||||
mSeq (mLedgerEntry->getFieldU32 (sfSequence))
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
Json::Value Offer::getJson (int)
|
||||
{
|
||||
Json::Value ret (Json::objectValue);
|
||||
ret["account"] = mAccount.humanAccountID ();
|
||||
ret["taker_gets"] = getTakerGets ().getFullText ();
|
||||
ret["taker_pays"] = getTakerPays ().getFullText ();
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // ripple
|
||||
70
src/ripple/module/app/misc/Offer.h
Normal file
70
src/ripple/module/app/misc/Offer.h
Normal file
@@ -0,0 +1,70 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_OFFER_H
|
||||
#define RIPPLE_OFFER_H
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class Offer : public AccountItem
|
||||
{
|
||||
public:
|
||||
Offer () {}
|
||||
|
||||
virtual ~Offer () {}
|
||||
|
||||
AccountItem::pointer makeItem (const uint160&, SerializedLedgerEntry::ref ledgerEntry);
|
||||
|
||||
LedgerEntryType getType ()
|
||||
{
|
||||
return (ltOFFER);
|
||||
}
|
||||
|
||||
const STAmount& getTakerPays ()
|
||||
{
|
||||
return (mTakerPays);
|
||||
}
|
||||
const STAmount& getTakerGets ()
|
||||
{
|
||||
return (mTakerGets);
|
||||
}
|
||||
const RippleAddress& getAccount ()
|
||||
{
|
||||
return (mAccount);
|
||||
}
|
||||
int getSeq ()
|
||||
{
|
||||
return (mSeq);
|
||||
}
|
||||
Json::Value getJson (int);
|
||||
|
||||
private:
|
||||
// For accounts in a ledger
|
||||
explicit Offer (SerializedLedgerEntry::pointer ledgerEntry);
|
||||
|
||||
private:
|
||||
RippleAddress mAccount;
|
||||
STAmount mTakerGets;
|
||||
STAmount mTakerPays;
|
||||
int mSeq;
|
||||
};
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
35
src/ripple/module/app/misc/OrderBook.cpp
Normal file
35
src/ripple/module/app/misc/OrderBook.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
namespace ripple {
|
||||
|
||||
OrderBook::OrderBook (uint256 const& index,
|
||||
uint160 const& currencyIn,
|
||||
uint160 const& currencyOut,
|
||||
uint160 const& issuerIn,
|
||||
uint160 const& issuerOut)
|
||||
: mBookBase (index)
|
||||
, mCurrencyIn (currencyIn)
|
||||
, mCurrencyOut (currencyOut)
|
||||
, mIssuerIn (issuerIn)
|
||||
, mIssuerOut (issuerOut)
|
||||
{
|
||||
}
|
||||
|
||||
} // ripple
|
||||
87
src/ripple/module/app/misc/OrderBook.h
Normal file
87
src/ripple/module/app/misc/OrderBook.h
Normal file
@@ -0,0 +1,87 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_ORDERBOOK_H
|
||||
#define RIPPLE_ORDERBOOK_H
|
||||
|
||||
namespace ripple {
|
||||
|
||||
/** Describes a serialized ledger entry for an order book. */
|
||||
class OrderBook : beast::LeakChecked <OrderBook>
|
||||
{
|
||||
public:
|
||||
typedef boost::shared_ptr <OrderBook> pointer;
|
||||
|
||||
typedef boost::shared_ptr <OrderBook> const& ref;
|
||||
|
||||
public:
|
||||
/** Construct from a currency specification.
|
||||
|
||||
@param index ???
|
||||
@param currencyIn The base currency.
|
||||
@param currencyOut The destination currency.
|
||||
@param issuerIn The base issuer.
|
||||
@param issuerOut The destination issuer.
|
||||
*/
|
||||
// VFALCO NOTE what is the meaning of the index parameter?
|
||||
// VFALCO TODO Replace with RippleAsset
|
||||
OrderBook (uint256 const& index,
|
||||
uint160 const& currencyIn,
|
||||
uint160 const& currencyOut,
|
||||
uint160 const& issuerIn,
|
||||
uint160 const& issuerOut);
|
||||
|
||||
uint256 const& getBookBase () const
|
||||
{
|
||||
return mBookBase;
|
||||
}
|
||||
|
||||
uint160 const& getCurrencyIn () const
|
||||
{
|
||||
return mCurrencyIn;
|
||||
}
|
||||
|
||||
uint160 const& getCurrencyOut () const
|
||||
{
|
||||
return mCurrencyOut;
|
||||
}
|
||||
|
||||
uint160 const& getIssuerIn () const
|
||||
{
|
||||
return mIssuerIn;
|
||||
}
|
||||
|
||||
uint160 const& getIssuerOut () const
|
||||
{
|
||||
return mIssuerOut;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
// VFALCO TODO Replace these with RippleAsset
|
||||
uint256 const mBookBase;
|
||||
uint160 const mCurrencyIn;
|
||||
uint160 const mCurrencyOut;
|
||||
uint160 const mIssuerIn;
|
||||
uint160 const mIssuerOut;
|
||||
};
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
37
src/ripple/module/app/misc/PowResult.h
Normal file
37
src/ripple/module/app/misc/PowResult.h
Normal file
@@ -0,0 +1,37 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_POWRESULT_H_INCLUDED
|
||||
#define RIPPLE_POWRESULT_H_INCLUDED
|
||||
|
||||
namespace ripple {
|
||||
|
||||
enum PowResult
|
||||
{
|
||||
powOK = 0,
|
||||
powREUSED = 1, // already submitted
|
||||
powBADNONCE = 2, // you didn't solve it
|
||||
powEXPIRED = 3, // time is up
|
||||
powCORRUPT = 4,
|
||||
powTOOEASY = 5, // the difficulty increased too much while you solved it
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
198
src/ripple/module/app/misc/ProofOfWork.cpp
Normal file
198
src/ripple/module/app/misc/ProofOfWork.cpp
Normal file
@@ -0,0 +1,198 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
SETUP_LOG (ProofOfWork)
|
||||
|
||||
// VFALCO TODO Move these to a header
|
||||
const uint256 ProofOfWork::sMinTarget ("00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
|
||||
|
||||
ProofOfWork::ProofOfWork (const std::string& token,
|
||||
int iterations,
|
||||
uint256 const& challenge,
|
||||
uint256 const& target)
|
||||
: mToken (token)
|
||||
, mChallenge (challenge)
|
||||
, mTarget (target)
|
||||
, mIterations (iterations)
|
||||
{
|
||||
}
|
||||
|
||||
ProofOfWork::ProofOfWork (const std::string& token)
|
||||
{
|
||||
std::vector<std::string> fields;
|
||||
boost::split (fields, token, boost::algorithm::is_any_of ("-"));
|
||||
|
||||
if (fields.size () != 5)
|
||||
throw std::runtime_error ("invalid token");
|
||||
|
||||
mToken = token;
|
||||
mChallenge.SetHex (fields[0]);
|
||||
mTarget.SetHex (fields[1]);
|
||||
mIterations = beast::lexicalCast <int> (fields[2]);
|
||||
}
|
||||
|
||||
bool ProofOfWork::isValid () const
|
||||
{
|
||||
if ((mIterations <= kMaxIterations) && (mTarget >= sMinTarget))
|
||||
return true;
|
||||
|
||||
WriteLog (lsWARNING, ProofOfWork) << "Invalid PoW: " << mIterations << ", " << mTarget;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::uint64_t ProofOfWork::getDifficulty (uint256 const& target, int iterations)
|
||||
{
|
||||
// calculate the approximate number of hashes required to solve this proof of work
|
||||
if ((iterations > kMaxIterations) || (target < sMinTarget))
|
||||
{
|
||||
WriteLog (lsINFO, ProofOfWork) << "Iterations:" << iterations;
|
||||
WriteLog (lsINFO, ProofOfWork) << "MaxIterat: " << kMaxIterations;
|
||||
WriteLog (lsINFO, ProofOfWork) << "Target: " << target;
|
||||
WriteLog (lsINFO, ProofOfWork) << "MinTarget: " << sMinTarget;
|
||||
throw std::runtime_error ("invalid proof of work target/iteration");
|
||||
}
|
||||
|
||||
// more iterations means more hashes per iteration but also a larger final hash
|
||||
std::uint64_t difficulty = iterations + (iterations / 8);
|
||||
|
||||
// Multiply the number of hashes needed by 256 for each leading zero byte in the difficulty
|
||||
const unsigned char* ptr = target.begin ();
|
||||
|
||||
while (*ptr == 0)
|
||||
{
|
||||
difficulty *= 256;
|
||||
++ptr;
|
||||
}
|
||||
|
||||
difficulty = (difficulty * 256) / (*ptr + 1);
|
||||
|
||||
return difficulty;
|
||||
}
|
||||
|
||||
static uint256 getSHA512Half (const std::vector<uint256>& vec)
|
||||
{
|
||||
return Serializer::getSHA512Half (vec.front ().begin (), vec.size () * (256 / 8));
|
||||
}
|
||||
|
||||
uint256 ProofOfWork::solve (int maxIterations) const
|
||||
{
|
||||
if (!isValid ())
|
||||
throw std::runtime_error ("invalid proof of work target/iteration");
|
||||
|
||||
uint256 nonce;
|
||||
RandomNumbers::getInstance ().fill (&nonce);
|
||||
|
||||
std::vector<uint256> buf2;
|
||||
buf2.resize (mIterations);
|
||||
|
||||
std::vector<uint256> buf1;
|
||||
buf1.resize (3);
|
||||
buf1[0] = mChallenge;
|
||||
|
||||
while (maxIterations > 0)
|
||||
{
|
||||
buf1[1] = nonce;
|
||||
buf1[2].zero ();
|
||||
|
||||
for (int i = (mIterations - 1); i >= 0; --i)
|
||||
{
|
||||
buf1[2] = getSHA512Half (buf1);
|
||||
buf2[i] = buf1[2];
|
||||
}
|
||||
|
||||
if (getSHA512Half (buf2) <= mTarget)
|
||||
return nonce;
|
||||
|
||||
++nonce;
|
||||
--maxIterations;
|
||||
}
|
||||
|
||||
return uint256 ();
|
||||
}
|
||||
|
||||
bool ProofOfWork::checkSolution (uint256 const& solution) const
|
||||
{
|
||||
if (mIterations > kMaxIterations)
|
||||
return false;
|
||||
|
||||
std::vector<uint256> buf1;
|
||||
buf1.push_back (mChallenge);
|
||||
buf1.push_back (solution);
|
||||
buf1.push_back (uint256 ());
|
||||
|
||||
std::vector<uint256> buf2;
|
||||
buf2.resize (mIterations);
|
||||
|
||||
for (int i = (mIterations - 1); i >= 0; --i)
|
||||
{
|
||||
buf1[2] = getSHA512Half (buf1);
|
||||
buf2[i] = buf1[2];
|
||||
}
|
||||
|
||||
return getSHA512Half (buf2) <= mTarget;
|
||||
}
|
||||
|
||||
bool ProofOfWork::validateToken (const std::string& strToken)
|
||||
{
|
||||
static boost::regex reToken ("[[:xdigit:]]{64}-[[:xdigit:]]{64}-[[:digit:]]+-[[:digit:]]+-[[:xdigit:]]{64}");
|
||||
boost::smatch smMatch;
|
||||
|
||||
return boost::regex_match (strToken, smMatch, reToken);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
bool ProofOfWork::calcResultInfo (PowResult powCode, std::string& strToken, std::string& strHuman)
|
||||
{
|
||||
static struct
|
||||
{
|
||||
PowResult powCode;
|
||||
const char* cpToken;
|
||||
const char* cpHuman;
|
||||
} powResultInfoA[] =
|
||||
{
|
||||
{ powREUSED, "powREUSED", "Proof-of-work has already been used." },
|
||||
{ powBADNONCE, "powBADNONCE", "The solution does not meet the required difficulty." },
|
||||
{ powEXPIRED, "powEXPIRED", "Token is expired." },
|
||||
{ powCORRUPT, "powCORRUPT", "Invalid token." },
|
||||
{ powTOOEASY, "powTOOEASY", "Difficulty has increased since token was issued." },
|
||||
|
||||
{ powOK, "powOK", "Valid proof-of-work." },
|
||||
};
|
||||
|
||||
int iIndex = RIPPLE_ARRAYSIZE (powResultInfoA);
|
||||
|
||||
while (iIndex-- && powResultInfoA[iIndex].powCode != powCode)
|
||||
;
|
||||
|
||||
if (iIndex >= 0)
|
||||
{
|
||||
strToken = powResultInfoA[iIndex].cpToken;
|
||||
strHuman = powResultInfoA[iIndex].cpHuman;
|
||||
}
|
||||
|
||||
return iIndex >= 0;
|
||||
}
|
||||
|
||||
} // ripple
|
||||
83
src/ripple/module/app/misc/ProofOfWork.h
Normal file
83
src/ripple/module/app/misc/ProofOfWork.h
Normal file
@@ -0,0 +1,83 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_PROOFOFWORK_H
|
||||
#define RIPPLE_PROOFOFWORK_H
|
||||
|
||||
#include <ripple/module/app/misc/PowResult.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class ProofOfWork : beast::LeakChecked <ProofOfWork>
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
kMaxIterations = (1 << 23)
|
||||
};
|
||||
|
||||
typedef boost::shared_ptr <ProofOfWork> pointer;
|
||||
|
||||
ProofOfWork (const std::string& token,
|
||||
int iterations,
|
||||
uint256 const& challenge,
|
||||
uint256 const& target);
|
||||
|
||||
explicit ProofOfWork (const std::string& token);
|
||||
|
||||
bool isValid () const;
|
||||
|
||||
uint256 solve (int maxIterations = 2 * kMaxIterations) const;
|
||||
bool checkSolution (uint256 const& solution) const;
|
||||
|
||||
const std::string& getToken () const
|
||||
{
|
||||
return mToken;
|
||||
}
|
||||
uint256 const& getChallenge () const
|
||||
{
|
||||
return mChallenge;
|
||||
}
|
||||
|
||||
std::uint64_t getDifficulty () const
|
||||
{
|
||||
return getDifficulty (mTarget, mIterations);
|
||||
}
|
||||
|
||||
// approximate number of hashes needed to solve
|
||||
static std::uint64_t getDifficulty (uint256 const& target, int iterations);
|
||||
|
||||
static bool validateToken (const std::string& strToken);
|
||||
|
||||
static bool calcResultInfo (PowResult powCode, std::string& strToken, std::string& strHuman);
|
||||
|
||||
private:
|
||||
std::string mToken;
|
||||
uint256 mChallenge;
|
||||
uint256 mTarget;
|
||||
int mIterations;
|
||||
|
||||
static const uint256 sMinTarget;
|
||||
static const int maxIterations;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
427
src/ripple/module/app/misc/ProofOfWorkFactory.cpp
Normal file
427
src/ripple/module/app/misc/ProofOfWorkFactory.cpp
Normal file
@@ -0,0 +1,427 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <beast/unit_test/suite.h>
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class ProofOfWorkFactoryImp
|
||||
: public ProofOfWorkFactory
|
||||
, public beast::LeakChecked <ProofOfWorkFactoryImp>
|
||||
{
|
||||
public:
|
||||
typedef boost::bimap< boost::bimaps::multiset_of<time_t>,
|
||||
boost::bimaps::unordered_set_of<uint256> > powMap_t;
|
||||
|
||||
typedef powMap_t::value_type powMap_vt;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
ProofOfWorkFactoryImp ()
|
||||
: mValidTime (180)
|
||||
{
|
||||
setDifficulty (1);
|
||||
RandomNumbers::getInstance ().fillBytes (mSecret.begin (), mSecret.size ());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
enum
|
||||
{
|
||||
numPowEntries = kMaxDifficulty + 1
|
||||
};
|
||||
|
||||
struct PowEntry
|
||||
{
|
||||
const char* target;
|
||||
int iterations;
|
||||
};
|
||||
|
||||
typedef std::vector <PowEntry> PowEntries;
|
||||
|
||||
static PowEntries const& getPowEntries ()
|
||||
{
|
||||
struct StaticPowEntries
|
||||
{
|
||||
StaticPowEntries ()
|
||||
{
|
||||
// VFALCO TODO Make this array know its own size.
|
||||
//
|
||||
PowEntry entries [numPowEntries] =
|
||||
{
|
||||
// target iterations hashes memory
|
||||
{ "0CFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 65536 }, // 1451874, 2 MB
|
||||
{ "0CFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 98304 }, // 2177811, 3 MB
|
||||
{ "07FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 98304 }, // 3538944, 3 MB
|
||||
{ "0CFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 196608}, // 4355623, 6 MB
|
||||
|
||||
{ "07FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 131072}, // 4718592, 4 MB
|
||||
{ "0CFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 262144}, // 5807497, 8 MB
|
||||
{ "07FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 196608}, // 7077888, 6 MB
|
||||
{ "07FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 262144}, // 9437184, 8 MB
|
||||
|
||||
{ "07FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 393216}, // 14155776, 12MB
|
||||
{ "03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 393216}, // 28311552, 12MB
|
||||
{ "00CFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 262144}, // 92919965, 8 MB
|
||||
{ "00CFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 393216}, // 139379948, 12MB
|
||||
|
||||
{ "007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 262144}, // 150994944, 8 MB
|
||||
{ "007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 393216}, // 226492416, 12MB
|
||||
{ "000CFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 49152 }, // 278759896, 1.5MB
|
||||
{ "003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 262144}, // 301989888, 8 MB
|
||||
|
||||
{ "003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 393216}, // 452984832, 12MB
|
||||
{ "0007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 98304 }, // 905969664, 3 MB
|
||||
{ "000CFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 196608}, // 1115039586, 6 MB
|
||||
{ "000CFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 262144}, // 1486719448 8 MB
|
||||
|
||||
{ "000CFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 393216}, // 2230079172 12MB
|
||||
{ "0007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 262144}, // 2415919104, 8 MB
|
||||
{ "0007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 393216}, // 3623878656, 12MB
|
||||
{ "0003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 393216}, // 7247757312, 12MB
|
||||
|
||||
{ "0000CFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 262144}, // 23787511177, 8 MB
|
||||
{ "0000CFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 393216}, // 35681266766, 12MB
|
||||
{ "00003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 131072}, // 38654705664, 4 MB
|
||||
{ "00007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 262144}, // 38654705664, 8 MB
|
||||
|
||||
{ "00003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 196608}, // 57982058496, 6 MB
|
||||
{ "00007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 393216}, // 57982058496, 12MB
|
||||
{ "00003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 262144}, // 77309411328, 8 MB
|
||||
};
|
||||
|
||||
data.reserve (numPowEntries);
|
||||
|
||||
for (int i = 0; i < numPowEntries; ++i)
|
||||
data.push_back (entries [i]);
|
||||
}
|
||||
|
||||
std::vector <PowEntry> data;
|
||||
};
|
||||
|
||||
static StaticPowEntries list;
|
||||
|
||||
return list.data;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
static int getPowEntry (uint256 const& target, int iterations)
|
||||
{
|
||||
PowEntries const& entries (getPowEntries ());
|
||||
|
||||
for (int i = 0; i < numPowEntries; ++i)
|
||||
{
|
||||
if (entries [i].iterations == iterations)
|
||||
{
|
||||
uint256 t;
|
||||
t.SetHex (entries [i].target);
|
||||
|
||||
if (t == target)
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
ProofOfWork getProof ()
|
||||
{
|
||||
// challenge - target - iterations - time - validator
|
||||
static boost::format f ("%s-%s-%d-%d");
|
||||
|
||||
int now = static_cast<int> (time (nullptr) / 4);
|
||||
|
||||
uint256 challenge;
|
||||
RandomNumbers::getInstance ().fillBytes (challenge.begin (), challenge.size ());
|
||||
|
||||
ScopedLockType sl (mLock);
|
||||
|
||||
std::string s = boost::str (boost::format (f) % to_string (challenge) %
|
||||
to_string (mTarget) % mIterations % now);
|
||||
std::string c = to_string (mSecret) + s;
|
||||
s += "-" + to_string (Serializer::getSHA512Half (c));
|
||||
|
||||
return ProofOfWork (s, mIterations, challenge, mTarget);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
PowResult checkProof (const std::string& token, uint256 const& solution)
|
||||
{
|
||||
// VFALCO COmmented this out because Dave said it wasn't used
|
||||
// and also we dont have the lexicalCast from a vector of strings to a time_t
|
||||
|
||||
// challenge - target - iterations - time - validator
|
||||
|
||||
std::vector<std::string> fields;
|
||||
boost::split (fields, token, boost::algorithm::is_any_of ("-"));
|
||||
|
||||
if (fields.size () != 5)
|
||||
{
|
||||
WriteLog (lsDEBUG, ProofOfWork) << "PoW " << token << " is corrupt";
|
||||
return powCORRUPT;
|
||||
}
|
||||
|
||||
std::string v = to_string (mSecret) + fields[0] + "-" +
|
||||
fields[1] + "-" + fields[2] + "-" + fields[3];
|
||||
|
||||
if (fields[4] != to_string (Serializer::getSHA512Half (v)))
|
||||
{
|
||||
WriteLog (lsDEBUG, ProofOfWork) << "PoW " << token << " has a bad token";
|
||||
return powCORRUPT;
|
||||
}
|
||||
|
||||
uint256 challenge, target;
|
||||
challenge.SetHex (fields[0]);
|
||||
target.SetHex (fields[1]);
|
||||
|
||||
time_t t;
|
||||
#if 0
|
||||
// Broken with lexicalCast<> changes
|
||||
t = beast::lexicalCast <time_t> (fields[3]);
|
||||
#else
|
||||
t = static_cast <time_t> (beast::lexicalCast <std::uint64_t> (fields [3]));
|
||||
#endif
|
||||
|
||||
time_t now = time (nullptr);
|
||||
|
||||
int iterations = beast::lexicalCast <int> (fields[2]);
|
||||
|
||||
{
|
||||
ScopedLockType sl (mLock);
|
||||
|
||||
if ((t * 4) > (now + mValidTime))
|
||||
{
|
||||
WriteLog (lsDEBUG, ProofOfWork) << "PoW " << token << " has expired";
|
||||
return powEXPIRED;
|
||||
}
|
||||
|
||||
if (((iterations != mIterations) || (target != mTarget)) && getPowEntry (target, iterations) < (mPowEntry - 2))
|
||||
{
|
||||
// difficulty has increased more than two times since PoW requested
|
||||
WriteLog (lsINFO, ProofOfWork) << "Difficulty has increased since PoW requested";
|
||||
return powTOOEASY;
|
||||
}
|
||||
}
|
||||
|
||||
ProofOfWork pow (token, iterations, challenge, target);
|
||||
|
||||
if (!pow.checkSolution (solution))
|
||||
{
|
||||
WriteLog (lsDEBUG, ProofOfWork) << "PoW " << token << " has a bad nonce";
|
||||
return powBADNONCE;
|
||||
}
|
||||
|
||||
{
|
||||
ScopedLockType sl (mLock);
|
||||
|
||||
if (!mSolvedChallenges.insert (powMap_vt (now, challenge)).second)
|
||||
{
|
||||
WriteLog (lsDEBUG, ProofOfWork) << "PoW " << token << " has been reused";
|
||||
return powREUSED;
|
||||
}
|
||||
}
|
||||
|
||||
return powOK;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void sweep ()
|
||||
{
|
||||
time_t expire = time (nullptr) - mValidTime;
|
||||
|
||||
ScopedLockType sl (mLock);
|
||||
|
||||
do
|
||||
{
|
||||
powMap_t::left_map::iterator it = mSolvedChallenges.left.begin ();
|
||||
|
||||
if (it == mSolvedChallenges.left.end ())
|
||||
return;
|
||||
|
||||
if (it->first >= expire)
|
||||
return;
|
||||
|
||||
mSolvedChallenges.left.erase (it);
|
||||
}
|
||||
while (1);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void loadHigh ()
|
||||
{
|
||||
time_t now = time (nullptr);
|
||||
|
||||
ScopedLockType sl (mLock);
|
||||
|
||||
if (mLastDifficultyChange == now)
|
||||
return;
|
||||
|
||||
if (mPowEntry == 30)
|
||||
return;
|
||||
|
||||
++mPowEntry;
|
||||
mLastDifficultyChange = now;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void loadLow ()
|
||||
{
|
||||
time_t now = time (nullptr);
|
||||
|
||||
ScopedLockType sl (mLock);
|
||||
|
||||
if (mLastDifficultyChange == now)
|
||||
return;
|
||||
|
||||
if (mPowEntry == 0)
|
||||
return;
|
||||
|
||||
--mPowEntry;
|
||||
mLastDifficultyChange = now;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void setDifficulty (int i)
|
||||
{
|
||||
assert ((i >= 0) && (i <= kMaxDifficulty));
|
||||
time_t now = time (nullptr);
|
||||
|
||||
ScopedLockType sl (mLock);
|
||||
mPowEntry = i;
|
||||
PowEntries const& entries (getPowEntries ());
|
||||
mIterations = entries [i].iterations;
|
||||
mTarget.SetHex (entries [i].target);
|
||||
mLastDifficultyChange = now;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
std::uint64_t getDifficulty ()
|
||||
{
|
||||
return ProofOfWork::getDifficulty (mTarget, mIterations);
|
||||
}
|
||||
|
||||
uint256 const& getSecret () const
|
||||
{
|
||||
return mSecret;
|
||||
}
|
||||
|
||||
void setSecret (uint256 const& secret)
|
||||
{
|
||||
mSecret = secret;
|
||||
}
|
||||
|
||||
private:
|
||||
typedef RippleMutex LockType;
|
||||
typedef std::lock_guard <LockType> ScopedLockType;
|
||||
LockType mLock;
|
||||
|
||||
uint256 mSecret;
|
||||
int mIterations;
|
||||
uint256 mTarget;
|
||||
time_t mLastDifficultyChange;
|
||||
int mValidTime;
|
||||
int mPowEntry;
|
||||
|
||||
powMap_t mSolvedChallenges;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
ProofOfWorkFactory* ProofOfWorkFactory::New ()
|
||||
{
|
||||
return new ProofOfWorkFactoryImp;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class ProofOfWork_test : public beast::unit_test::suite
|
||||
{
|
||||
public:
|
||||
void run ()
|
||||
{
|
||||
using namespace ripple;
|
||||
|
||||
ProofOfWorkFactoryImp gen;
|
||||
ProofOfWork pow = gen.getProof ();
|
||||
|
||||
beast::String s;
|
||||
|
||||
s << "solve difficulty " << beast::String (pow.getDifficulty ());
|
||||
|
||||
uint256 solution = pow.solve (16777216);
|
||||
|
||||
expect (! solution.isZero (), "Should be solved");
|
||||
|
||||
expect (pow.checkSolution (solution), "Should be checked");
|
||||
|
||||
// Why is this emitted?
|
||||
//WriteLog (lsDEBUG, ProofOfWork) << "A bad nonce error is expected";
|
||||
|
||||
PowResult r = gen.checkProof (pow.getToken (), uint256 ());
|
||||
|
||||
expect (r == powBADNONCE, "Should show bad nonce for empty solution");
|
||||
|
||||
expect (gen.checkProof (pow.getToken (), solution) == powOK, "Solution should check with issuer");
|
||||
|
||||
//WriteLog (lsDEBUG, ProofOfWork) << "A reused nonce error is expected";
|
||||
|
||||
expect (gen.checkProof (pow.getToken (), solution) == powREUSED, "Reuse solution should be detected");
|
||||
|
||||
#ifdef SOLVE_POWS
|
||||
|
||||
for (int i = 0; i < 12; ++i)
|
||||
{
|
||||
gen.setDifficulty (i);
|
||||
ProofOfWork pow = gen.getProof ();
|
||||
WriteLog (lsINFO, ProofOfWork) << "Level: " << i << ", Estimated difficulty: " << pow.getDifficulty ();
|
||||
uint256 solution = pow.solve (131072);
|
||||
|
||||
if (solution.isZero ())
|
||||
{
|
||||
//WriteLog (lsINFO, ProofOfWork) << "Giving up";
|
||||
}
|
||||
else
|
||||
{
|
||||
//WriteLog (lsINFO, ProofOfWork) << "Solution found";
|
||||
|
||||
if (gen.checkProof (pow.getToken (), solution) != powOK)
|
||||
{
|
||||
//WriteLog (lsFATAL, ProofOfWork) << "Solution fails";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE_MANUAL(ProofOfWork,ripple_app,ripple);
|
||||
|
||||
} // ripple
|
||||
61
src/ripple/module/app/misc/ProofOfWorkFactory.h
Normal file
61
src/ripple/module/app/misc/ProofOfWorkFactory.h
Normal file
@@ -0,0 +1,61 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_PROOFOFWORKFACTORY_H_INCLUDED
|
||||
#define RIPPLE_PROOFOFWORKFACTORY_H_INCLUDED
|
||||
|
||||
#include <ripple/module/app/misc/PowResult.h>
|
||||
#include <ripple/module/app/misc/ProofOfWork.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class ProofOfWorkFactory
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
kMaxDifficulty = 30,
|
||||
};
|
||||
|
||||
static ProofOfWorkFactory* New ();
|
||||
|
||||
virtual ~ProofOfWorkFactory () { }
|
||||
|
||||
virtual ProofOfWork getProof () = 0;
|
||||
|
||||
virtual PowResult checkProof (const std::string& token, uint256 const& solution) = 0;
|
||||
|
||||
virtual std::uint64_t getDifficulty () = 0;
|
||||
|
||||
virtual void setDifficulty (int i) = 0;
|
||||
|
||||
virtual void loadHigh () = 0;
|
||||
|
||||
virtual void loadLow () = 0;
|
||||
|
||||
virtual void sweep () = 0;
|
||||
|
||||
virtual uint256 const& getSecret () const = 0;
|
||||
|
||||
virtual void setSecret (uint256 const& secret) = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
30
src/ripple/module/app/misc/README.md
Normal file
30
src/ripple/module/app/misc/README.md
Normal 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.
|
||||
221
src/ripple/module/app/misc/SerializedLedger.cpp
Normal file
221
src/ripple/module/app/misc/SerializedLedger.cpp
Normal file
@@ -0,0 +1,221 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
namespace ripple {
|
||||
|
||||
struct SerializedLedgerLog; // for Log
|
||||
|
||||
SETUP_LOGN (SerializedLedgerLog,"SerializedLedger")
|
||||
|
||||
SerializedLedgerEntry::SerializedLedgerEntry (
|
||||
SerializerIterator& sit, uint256 const& index)
|
||||
: STObject (sfLedgerEntry), mIndex (index), mMutable (true)
|
||||
{
|
||||
set (sit);
|
||||
setSLEType ();
|
||||
}
|
||||
|
||||
SerializedLedgerEntry::SerializedLedgerEntry (
|
||||
const Serializer& s, uint256 const& index)
|
||||
: STObject (sfLedgerEntry), mIndex (index), mMutable (true)
|
||||
{
|
||||
// we know 's' isn't going away
|
||||
SerializerIterator sit (const_cast<Serializer&> (s));
|
||||
set (sit);
|
||||
setSLEType ();
|
||||
}
|
||||
|
||||
SerializedLedgerEntry::SerializedLedgerEntry (
|
||||
const STObject & object, uint256 const& index)
|
||||
: STObject (object), mIndex(index), mMutable (true)
|
||||
{
|
||||
setSLEType ();
|
||||
}
|
||||
|
||||
void SerializedLedgerEntry::setSLEType ()
|
||||
{
|
||||
auto type = static_cast <LedgerEntryType> (getFieldU16 (sfLedgerEntryType));
|
||||
auto const item = LedgerFormats::getInstance()->findByType (type);
|
||||
|
||||
if (item == nullptr)
|
||||
throw std::runtime_error ("invalid ledger entry type");
|
||||
|
||||
mType = item->getType ();
|
||||
if (!setType (item->elements))
|
||||
{
|
||||
WriteLog (lsWARNING, SerializedLedgerLog)
|
||||
<< "Ledger entry not valid for type " << mFormat->getName ();
|
||||
WriteLog (lsWARNING, SerializedLedgerLog) << getJson (0);
|
||||
throw std::runtime_error ("ledger entry not valid for type");
|
||||
}
|
||||
}
|
||||
|
||||
SerializedLedgerEntry::SerializedLedgerEntry (LedgerEntryType type, uint256 const& index) :
|
||||
STObject (sfLedgerEntry), mIndex (index), mType (type), mMutable (true)
|
||||
{
|
||||
LedgerFormats::Item const* const item =
|
||||
LedgerFormats::getInstance()->findByType (type);
|
||||
|
||||
if (item != nullptr)
|
||||
{
|
||||
set (item->elements);
|
||||
|
||||
setFieldU16 (sfLedgerEntryType, static_cast <std::uint16_t> (item->getType ()));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error ("invalid ledger entry type");
|
||||
}
|
||||
}
|
||||
|
||||
SerializedLedgerEntry::pointer SerializedLedgerEntry::getMutable () const
|
||||
{
|
||||
SerializedLedgerEntry::pointer ret = boost::make_shared<SerializedLedgerEntry> (boost::cref (*this));
|
||||
ret->mMutable = true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string SerializedLedgerEntry::getFullText () const
|
||||
{
|
||||
std::string ret = "\"";
|
||||
ret += to_string (mIndex);
|
||||
ret += "\" = { ";
|
||||
ret += mFormat->getName ();
|
||||
ret += ", ";
|
||||
ret += STObject::getFullText ();
|
||||
ret += "}";
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string SerializedLedgerEntry::getText () const
|
||||
{
|
||||
return str (boost::format ("{ %s, %s }")
|
||||
% to_string (mIndex)
|
||||
% STObject::getText ());
|
||||
}
|
||||
|
||||
Json::Value SerializedLedgerEntry::getJson (int options) const
|
||||
{
|
||||
Json::Value ret (STObject::getJson (options));
|
||||
|
||||
ret["index"] = to_string (mIndex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool SerializedLedgerEntry::isThreadedType ()
|
||||
{
|
||||
return getFieldIndex (sfPreviousTxnID) != -1;
|
||||
}
|
||||
|
||||
bool SerializedLedgerEntry::isThreaded ()
|
||||
{
|
||||
return isFieldPresent (sfPreviousTxnID);
|
||||
}
|
||||
|
||||
uint256 SerializedLedgerEntry::getThreadedTransaction ()
|
||||
{
|
||||
return getFieldH256 (sfPreviousTxnID);
|
||||
}
|
||||
|
||||
std::uint32_t SerializedLedgerEntry::getThreadedLedger ()
|
||||
{
|
||||
return getFieldU32 (sfPreviousTxnLgrSeq);
|
||||
}
|
||||
|
||||
bool SerializedLedgerEntry::thread (uint256 const& txID, std::uint32_t ledgerSeq,
|
||||
uint256& prevTxID, std::uint32_t& prevLedgerID)
|
||||
{
|
||||
uint256 oldPrevTxID = getFieldH256 (sfPreviousTxnID);
|
||||
WriteLog (lsTRACE, SerializedLedgerLog) << "Thread Tx:" << txID << " prev:" << oldPrevTxID;
|
||||
|
||||
if (oldPrevTxID == txID)
|
||||
{
|
||||
// this transaction is already threaded
|
||||
assert (getFieldU32 (sfPreviousTxnLgrSeq) == ledgerSeq);
|
||||
return false;
|
||||
}
|
||||
|
||||
prevTxID = oldPrevTxID;
|
||||
prevLedgerID = getFieldU32 (sfPreviousTxnLgrSeq);
|
||||
setFieldH256 (sfPreviousTxnID, txID);
|
||||
setFieldU32 (sfPreviousTxnLgrSeq, ledgerSeq);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SerializedLedgerEntry::hasOneOwner ()
|
||||
{
|
||||
return (mType != ltACCOUNT_ROOT) && (getFieldIndex (sfAccount) != -1);
|
||||
}
|
||||
|
||||
bool SerializedLedgerEntry::hasTwoOwners ()
|
||||
{
|
||||
return mType == ltRIPPLE_STATE;
|
||||
}
|
||||
|
||||
RippleAddress SerializedLedgerEntry::getOwner ()
|
||||
{
|
||||
return getFieldAccount (sfAccount);
|
||||
}
|
||||
|
||||
RippleAddress SerializedLedgerEntry::getFirstOwner ()
|
||||
{
|
||||
return RippleAddress::createAccountID (getFieldAmount (sfLowLimit).getIssuer ());
|
||||
}
|
||||
|
||||
RippleAddress SerializedLedgerEntry::getSecondOwner ()
|
||||
{
|
||||
return RippleAddress::createAccountID (getFieldAmount (sfHighLimit).getIssuer ());
|
||||
}
|
||||
|
||||
std::vector<uint256> SerializedLedgerEntry::getOwners ()
|
||||
{
|
||||
std::vector<uint256> owners;
|
||||
uint160 account;
|
||||
|
||||
for (int i = 0, fields = getCount (); i < fields; ++i)
|
||||
{
|
||||
SField::ref fc = getFieldSType (i);
|
||||
|
||||
if ((fc == sfAccount) || (fc == sfOwner))
|
||||
{
|
||||
const STAccount* entry = dynamic_cast<const STAccount*> (peekAtPIndex (i));
|
||||
|
||||
if ((entry != nullptr) && entry->getValueH160 (account))
|
||||
owners.push_back (Ledger::getAccountRootIndex (account));
|
||||
}
|
||||
|
||||
if ((fc == sfLowLimit) || (fc == sfHighLimit))
|
||||
{
|
||||
const STAmount* entry = dynamic_cast<const STAmount*> (peekAtPIndex (i));
|
||||
|
||||
if ((entry != nullptr))
|
||||
{
|
||||
uint160 issuer = entry->getIssuer ();
|
||||
|
||||
if (issuer.isNonZero ())
|
||||
owners.push_back (Ledger::getAccountRootIndex (issuer));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return owners;
|
||||
}
|
||||
|
||||
} // ripple
|
||||
132
src/ripple/module/app/misc/SerializedLedger.h
Normal file
132
src/ripple/module/app/misc/SerializedLedger.h
Normal file
@@ -0,0 +1,132 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_SERIALIZEDLEDGER_H
|
||||
#define RIPPLE_SERIALIZEDLEDGER_H
|
||||
|
||||
namespace ripple {
|
||||
|
||||
// VFALCO NOTE
|
||||
//
|
||||
// This looks like a central class for Ripple. Almost everything that
|
||||
// does anything of interest deals with SLE objects. Any documentation
|
||||
// effort should start with a complete description of this object and
|
||||
// all of its operations.
|
||||
//
|
||||
// It is derived from STObject so it inherits a lot of behavior from that.
|
||||
//
|
||||
// VFALCO TODO Rename the source file to match the class
|
||||
//
|
||||
// VFALCO TODO Can we rename this class to something shorter and more concise?
|
||||
//
|
||||
// Can we just call this LedgerEntry?
|
||||
//
|
||||
class SerializedLedgerEntry
|
||||
: public STObject
|
||||
, public CountedObject <SerializedLedgerEntry>
|
||||
{
|
||||
public:
|
||||
static char const* getCountedObjectName () { return "SerializedLedgerEntry"; }
|
||||
|
||||
typedef boost::shared_ptr<SerializedLedgerEntry> pointer;
|
||||
typedef const boost::shared_ptr<SerializedLedgerEntry>& ref;
|
||||
|
||||
public:
|
||||
SerializedLedgerEntry (const Serializer & s, uint256 const & index);
|
||||
SerializedLedgerEntry (SerializerIterator & sit, uint256 const & index);
|
||||
SerializedLedgerEntry (LedgerEntryType type, uint256 const & index);
|
||||
SerializedLedgerEntry (const STObject & object, uint256 const & index);
|
||||
|
||||
SerializedTypeID getSType () const
|
||||
{
|
||||
return STI_LEDGERENTRY;
|
||||
}
|
||||
std::string getFullText () const;
|
||||
std::string getText () const;
|
||||
Json::Value getJson (int options) const;
|
||||
|
||||
uint256 const& getIndex () const
|
||||
{
|
||||
return mIndex;
|
||||
}
|
||||
void setIndex (uint256 const & i)
|
||||
{
|
||||
mIndex = i;
|
||||
}
|
||||
|
||||
void setImmutable ()
|
||||
{
|
||||
mMutable = false;
|
||||
}
|
||||
bool isMutable ()
|
||||
{
|
||||
return mMutable;
|
||||
}
|
||||
SerializedLedgerEntry::pointer getMutable () const;
|
||||
|
||||
LedgerEntryType getType () const
|
||||
{
|
||||
return mType;
|
||||
}
|
||||
std::uint16_t getVersion () const
|
||||
{
|
||||
return getFieldU16 (sfLedgerEntryType);
|
||||
}
|
||||
LedgerFormats::Item const* getFormat ()
|
||||
{
|
||||
return mFormat;
|
||||
}
|
||||
|
||||
bool isThreadedType (); // is this a ledger entry that can be threaded
|
||||
bool isThreaded (); // is this ledger entry actually threaded
|
||||
bool hasOneOwner (); // This node has one other node that owns it (like nickname)
|
||||
bool hasTwoOwners (); // This node has two nodes that own it (like ripple balance)
|
||||
RippleAddress getOwner ();
|
||||
RippleAddress getFirstOwner ();
|
||||
RippleAddress getSecondOwner ();
|
||||
uint256 getThreadedTransaction ();
|
||||
std::uint32_t getThreadedLedger ();
|
||||
bool thread (uint256 const & txID, std::uint32_t ledgerSeq, uint256 & prevTxID,
|
||||
std::uint32_t & prevLedgerID);
|
||||
std::vector<uint256> getOwners (); // nodes notified if this node is deleted
|
||||
|
||||
private:
|
||||
SerializedLedgerEntry* duplicate () const
|
||||
{
|
||||
return new SerializedLedgerEntry (*this);
|
||||
}
|
||||
|
||||
/** Make STObject comply with the template for this SLE type
|
||||
Can throw
|
||||
*/
|
||||
void setSLEType ();
|
||||
|
||||
private:
|
||||
uint256 mIndex;
|
||||
LedgerEntryType mType;
|
||||
LedgerFormats::Item const* mFormat;
|
||||
bool mMutable;
|
||||
};
|
||||
|
||||
typedef SerializedLedgerEntry SLE;
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
|
||||
427
src/ripple/module/app/misc/SerializedTransaction.cpp
Normal file
427
src/ripple/module/app/misc/SerializedTransaction.cpp
Normal file
@@ -0,0 +1,427 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <beast/unit_test/suite.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
SETUP_LOG (SerializedTransaction)
|
||||
|
||||
SerializedTransaction::SerializedTransaction (TxType type)
|
||||
: STObject (sfTransaction)
|
||||
, mType (type)
|
||||
, mSigGood (false)
|
||||
, mSigBad (false)
|
||||
{
|
||||
mFormat = TxFormats::getInstance()->findByType (type);
|
||||
|
||||
if (mFormat == nullptr)
|
||||
{
|
||||
WriteLog (lsWARNING, SerializedTransaction) << "Transaction type: " << type;
|
||||
throw std::runtime_error ("invalid transaction type");
|
||||
}
|
||||
|
||||
set (mFormat->elements);
|
||||
setFieldU16 (sfTransactionType, mFormat->getType ());
|
||||
}
|
||||
|
||||
SerializedTransaction::SerializedTransaction (STObject const& object)
|
||||
: STObject (object)
|
||||
, mSigGood (false)
|
||||
, mSigBad (false)
|
||||
{
|
||||
mType = static_cast <TxType> (getFieldU16 (sfTransactionType));
|
||||
|
||||
mFormat = TxFormats::getInstance()->findByType (mType);
|
||||
|
||||
if (!mFormat)
|
||||
{
|
||||
WriteLog (lsWARNING, SerializedTransaction) << "Transaction type: " << mType;
|
||||
throw std::runtime_error ("invalid transaction type");
|
||||
}
|
||||
|
||||
if (!setType (mFormat->elements))
|
||||
{
|
||||
throw std::runtime_error ("transaction not valid");
|
||||
}
|
||||
}
|
||||
|
||||
SerializedTransaction::SerializedTransaction (SerializerIterator& sit) : STObject (sfTransaction),
|
||||
mSigGood (false), mSigBad (false)
|
||||
{
|
||||
int length = sit.getBytesLeft ();
|
||||
|
||||
if ((length < Protocol::txMinSizeBytes) || (length > Protocol::txMaxSizeBytes))
|
||||
{
|
||||
Log (lsERROR) << "Transaction has invalid length: " << length;
|
||||
throw std::runtime_error ("Transaction length invalid");
|
||||
}
|
||||
|
||||
set (sit);
|
||||
mType = static_cast<TxType> (getFieldU16 (sfTransactionType));
|
||||
|
||||
mFormat = TxFormats::getInstance()->findByType (mType);
|
||||
|
||||
if (!mFormat)
|
||||
{
|
||||
WriteLog (lsWARNING, SerializedTransaction) << "Transaction type: " << mType;
|
||||
throw std::runtime_error ("invalid transaction type");
|
||||
}
|
||||
|
||||
if (!setType (mFormat->elements))
|
||||
{
|
||||
WriteLog (lsWARNING, SerializedTransaction) << "Transaction not legal for format";
|
||||
throw std::runtime_error ("transaction not valid");
|
||||
}
|
||||
}
|
||||
|
||||
std::string SerializedTransaction::getFullText () const
|
||||
{
|
||||
std::string ret = "\"";
|
||||
ret += to_string (getTransactionID ());
|
||||
ret += "\" = {";
|
||||
ret += STObject::getFullText ();
|
||||
ret += "}";
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string SerializedTransaction::getText () const
|
||||
{
|
||||
return STObject::getText ();
|
||||
}
|
||||
|
||||
std::vector<RippleAddress> SerializedTransaction::getMentionedAccounts () const
|
||||
{
|
||||
std::vector<RippleAddress> accounts;
|
||||
|
||||
BOOST_FOREACH (const SerializedType & it, peekData ())
|
||||
{
|
||||
const STAccount* sa = dynamic_cast<const STAccount*> (&it);
|
||||
|
||||
if (sa != nullptr)
|
||||
{
|
||||
bool found = false;
|
||||
RippleAddress na = sa->getValueNCA ();
|
||||
BOOST_FOREACH (const RippleAddress & it, accounts)
|
||||
{
|
||||
if (it == na)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
accounts.push_back (na);
|
||||
}
|
||||
|
||||
const STAmount* sam = dynamic_cast<const STAmount*> (&it);
|
||||
|
||||
if (sam)
|
||||
{
|
||||
uint160 issuer = sam->getIssuer ();
|
||||
|
||||
if (issuer.isNonZero ())
|
||||
{
|
||||
RippleAddress na;
|
||||
na.setAccountID (issuer);
|
||||
bool found = false;
|
||||
BOOST_FOREACH (const RippleAddress & it, accounts)
|
||||
{
|
||||
if (it == na)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
accounts.push_back (na);
|
||||
}
|
||||
}
|
||||
}
|
||||
return accounts;
|
||||
}
|
||||
|
||||
uint256 SerializedTransaction::getSigningHash () const
|
||||
{
|
||||
return STObject::getSigningHash (getConfig ().SIGN_TRANSACTION);
|
||||
}
|
||||
|
||||
uint256 SerializedTransaction::getTransactionID () const
|
||||
{
|
||||
// perhaps we should cache this
|
||||
return getHash (HashPrefix::transactionID);
|
||||
}
|
||||
|
||||
Blob SerializedTransaction::getSignature () const
|
||||
{
|
||||
try
|
||||
{
|
||||
return getFieldVL (sfTxnSignature);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return Blob ();
|
||||
}
|
||||
}
|
||||
|
||||
void SerializedTransaction::sign (const RippleAddress& naAccountPrivate)
|
||||
{
|
||||
Blob signature;
|
||||
naAccountPrivate.accountPrivateSign (getSigningHash (), signature);
|
||||
setFieldVL (sfTxnSignature, signature);
|
||||
}
|
||||
|
||||
bool SerializedTransaction::checkSign () const
|
||||
{
|
||||
if (mSigGood)
|
||||
return true;
|
||||
|
||||
if (mSigBad)
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
RippleAddress n;
|
||||
n.setAccountPublic (getFieldVL (sfSigningPubKey));
|
||||
|
||||
if (checkSign (n))
|
||||
{
|
||||
mSigGood = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
mSigBad = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SerializedTransaction::checkSign (const RippleAddress& naAccountPublic) const
|
||||
{
|
||||
try
|
||||
{
|
||||
const ECDSA fullyCanonical = (getFlags() & tfFullyCanonicalSig) ?
|
||||
ECDSA::strict : ECDSA::not_strict;
|
||||
return naAccountPublic.accountPublicVerify (getSigningHash (), getFieldVL (sfTxnSignature), fullyCanonical);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void SerializedTransaction::setSigningPubKey (const RippleAddress& naSignPubKey)
|
||||
{
|
||||
setFieldVL (sfSigningPubKey, naSignPubKey.getAccountPublic ());
|
||||
}
|
||||
|
||||
void SerializedTransaction::setSourceAccount (const RippleAddress& naSource)
|
||||
{
|
||||
setFieldAccount (sfAccount, naSource);
|
||||
}
|
||||
|
||||
Json::Value SerializedTransaction::getJson (int) const
|
||||
{
|
||||
Json::Value ret = STObject::getJson (0);
|
||||
ret["hash"] = to_string (getTransactionID ());
|
||||
return ret;
|
||||
}
|
||||
|
||||
Json::Value SerializedTransaction::getJson (int options, bool binary) const
|
||||
{
|
||||
if (binary)
|
||||
{
|
||||
Json::Value ret;
|
||||
Serializer s = STObject::getSerializer ();
|
||||
ret["tx"] = strHex (s.peekData ());
|
||||
ret["hash"] = to_string (getTransactionID ());
|
||||
return ret;
|
||||
}
|
||||
return getJson(options);
|
||||
}
|
||||
|
||||
std::string SerializedTransaction::getSQLValueHeader ()
|
||||
{
|
||||
return "(TransID, TransType, FromAcct, FromSeq, LedgerSeq, Status, RawTxn)";
|
||||
}
|
||||
|
||||
std::string SerializedTransaction::getMetaSQLValueHeader ()
|
||||
{
|
||||
return "(TransID, TransType, FromAcct, FromSeq, LedgerSeq, Status, RawTxn, TxnMeta)";
|
||||
}
|
||||
|
||||
std::string SerializedTransaction::getMetaSQLInsertReplaceHeader ()
|
||||
{
|
||||
return "INSERT OR REPLACE INTO Transactions " + getMetaSQLValueHeader () + " VALUES ";
|
||||
}
|
||||
|
||||
std::string SerializedTransaction::getSQL (std::uint32_t inLedger, char status) const
|
||||
{
|
||||
Serializer s;
|
||||
add (s);
|
||||
return getSQL (s, inLedger, status);
|
||||
}
|
||||
|
||||
std::string SerializedTransaction::getMetaSQL (std::uint32_t inLedger,
|
||||
const std::string& escapedMetaData) const
|
||||
{
|
||||
Serializer s;
|
||||
add (s);
|
||||
return getMetaSQL (s, inLedger, TXN_SQL_VALIDATED, escapedMetaData);
|
||||
}
|
||||
|
||||
std::string SerializedTransaction::getSQL (Serializer rawTxn, std::uint32_t inLedger, char status) const
|
||||
{
|
||||
static boost::format bfTrans ("('%s', '%s', '%s', '%d', '%d', '%c', %s)");
|
||||
std::string rTxn = sqlEscape (rawTxn.peekData ());
|
||||
|
||||
return str (boost::format (bfTrans)
|
||||
% to_string (getTransactionID ()) % getTransactionType ()
|
||||
% getSourceAccount ().humanAccountID ()
|
||||
% getSequence () % inLedger % status % rTxn);
|
||||
}
|
||||
|
||||
std::string SerializedTransaction::getMetaSQL (Serializer rawTxn, std::uint32_t inLedger, char status,
|
||||
const std::string& escapedMetaData) const
|
||||
{
|
||||
static boost::format bfTrans ("('%s', '%s', '%s', '%d', '%d', '%c', %s, %s)");
|
||||
std::string rTxn = sqlEscape (rawTxn.peekData ());
|
||||
|
||||
return str (boost::format (bfTrans)
|
||||
% to_string (getTransactionID ()) % getTransactionType ()
|
||||
% getSourceAccount ().humanAccountID ()
|
||||
% getSequence () % inLedger % status % rTxn % escapedMetaData);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
bool isMemoOkay (STObject const& st)
|
||||
{
|
||||
if (!st.isFieldPresent (sfMemos))
|
||||
return true;
|
||||
// The number 2048 is a preallocation hint, not a hard limit
|
||||
// to avoid allocate/copy/free's
|
||||
Serializer s (2048);
|
||||
st.getFieldArray (sfMemos).add (s);
|
||||
// FIXME move the memo limit into a config tunable
|
||||
if (s.getDataLength () > 1024)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Ensure all account fields are 160-bits
|
||||
bool isAccountFieldOkay (STObject const& st)
|
||||
{
|
||||
for (int i = 0; i < st.getCount(); ++i)
|
||||
{
|
||||
const STAccount* t = dynamic_cast<STAccount const*>(st.peekAtPIndex (i));
|
||||
if (t&& !t->isValueH160 ())
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool passesLocalChecks (STObject const& st, std::string& reason)
|
||||
{
|
||||
if (!isMemoOkay (st))
|
||||
{
|
||||
reason = "The memo exceeds the maximum allowed size.";
|
||||
return false;
|
||||
}
|
||||
if (!isAccountFieldOkay (st))
|
||||
{
|
||||
reason = "An account field is invalid.";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool passesLocalChecks (STObject const& st)
|
||||
{
|
||||
std::string reason;
|
||||
return passesLocalChecks (st, reason);
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class SerializedTransaction_test : public beast::unit_test::suite
|
||||
{
|
||||
public:
|
||||
void run()
|
||||
{
|
||||
RippleAddress seed;
|
||||
seed.setSeedRandom ();
|
||||
RippleAddress generator = RippleAddress::createGeneratorPublic (seed);
|
||||
RippleAddress publicAcct = RippleAddress::createAccountPublic (generator, 1);
|
||||
RippleAddress privateAcct = RippleAddress::createAccountPrivate (generator, seed, 1);
|
||||
|
||||
SerializedTransaction j (ttACCOUNT_SET);
|
||||
j.setSourceAccount (publicAcct);
|
||||
j.setSigningPubKey (publicAcct);
|
||||
j.setFieldVL (sfMessageKey, publicAcct.getAccountPublic ());
|
||||
j.sign (privateAcct);
|
||||
|
||||
unexpected (!j.checkSign (), "Transaction fails signature test");
|
||||
|
||||
Serializer rawTxn;
|
||||
j.add (rawTxn);
|
||||
SerializerIterator sit (rawTxn);
|
||||
SerializedTransaction copy (sit);
|
||||
|
||||
if (copy != j)
|
||||
{
|
||||
log << j.getJson (0);
|
||||
log << copy.getJson (0);
|
||||
fail ("Transaction fails serialize/deserialize test");
|
||||
}
|
||||
else
|
||||
{
|
||||
pass ();
|
||||
}
|
||||
|
||||
STParsedJSON parsed ("test", j.getJson (0));
|
||||
std::unique_ptr <STObject> new_obj (std::move (parsed.object));
|
||||
|
||||
if (new_obj.get () == nullptr)
|
||||
fail ("Unable to build object from json");
|
||||
|
||||
if (STObject (j) != *new_obj)
|
||||
{
|
||||
log << "ORIG: " << j.getJson (0);
|
||||
log << "BUILT " << new_obj->getJson (0);
|
||||
fail ("Built a different transaction");
|
||||
}
|
||||
else
|
||||
{
|
||||
pass ();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(SerializedTransaction,ripple_app,ripple);
|
||||
|
||||
} // ripple
|
||||
161
src/ripple/module/app/misc/SerializedTransaction.h
Normal file
161
src/ripple/module/app/misc/SerializedTransaction.h
Normal file
@@ -0,0 +1,161 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_SERIALIZEDTRANSACTION_H
|
||||
#define RIPPLE_SERIALIZEDTRANSACTION_H
|
||||
|
||||
namespace ripple {
|
||||
|
||||
// VFALCO TODO replace these macros with language constants
|
||||
|
||||
#define TXN_SQL_NEW 'N'
|
||||
#define TXN_SQL_CONFLICT 'C'
|
||||
#define TXN_SQL_HELD 'H'
|
||||
#define TXN_SQL_VALIDATED 'V'
|
||||
#define TXN_SQL_INCLUDED 'I'
|
||||
#define TXN_SQL_UNKNOWN 'U'
|
||||
|
||||
class SerializedTransaction
|
||||
: public STObject
|
||||
, public CountedObject <SerializedTransaction>
|
||||
{
|
||||
public:
|
||||
static char const* getCountedObjectName () { return "SerializedTransaction"; }
|
||||
|
||||
typedef boost::shared_ptr<SerializedTransaction> pointer;
|
||||
typedef const boost::shared_ptr<SerializedTransaction>& ref;
|
||||
|
||||
public:
|
||||
SerializedTransaction (SerializerIterator & sit);
|
||||
SerializedTransaction (TxType type);
|
||||
SerializedTransaction (const STObject & object);
|
||||
|
||||
// STObject functions
|
||||
SerializedTypeID getSType () const
|
||||
{
|
||||
return STI_TRANSACTION;
|
||||
}
|
||||
std::string getFullText () const;
|
||||
std::string getText () const;
|
||||
|
||||
// outer transaction functions / signature functions
|
||||
Blob getSignature () const;
|
||||
void setSignature (Blob const & s)
|
||||
{
|
||||
setFieldVL (sfTxnSignature, s);
|
||||
}
|
||||
uint256 getSigningHash () const;
|
||||
|
||||
TxType getTxnType () const
|
||||
{
|
||||
return mType;
|
||||
}
|
||||
STAmount getTransactionFee () const
|
||||
{
|
||||
return getFieldAmount (sfFee);
|
||||
}
|
||||
void setTransactionFee (const STAmount & fee)
|
||||
{
|
||||
setFieldAmount (sfFee, fee);
|
||||
}
|
||||
|
||||
RippleAddress getSourceAccount () const
|
||||
{
|
||||
return getFieldAccount (sfAccount);
|
||||
}
|
||||
Blob getSigningPubKey () const
|
||||
{
|
||||
return getFieldVL (sfSigningPubKey);
|
||||
}
|
||||
void setSigningPubKey (const RippleAddress & naSignPubKey);
|
||||
void setSourceAccount (const RippleAddress & naSource);
|
||||
std::string getTransactionType () const
|
||||
{
|
||||
return mFormat->getName ();
|
||||
}
|
||||
|
||||
std::uint32_t getSequence () const
|
||||
{
|
||||
return getFieldU32 (sfSequence);
|
||||
}
|
||||
void setSequence (std::uint32_t seq)
|
||||
{
|
||||
return setFieldU32 (sfSequence, seq);
|
||||
}
|
||||
|
||||
std::vector<RippleAddress> getMentionedAccounts () const;
|
||||
|
||||
uint256 getTransactionID () const;
|
||||
|
||||
virtual Json::Value getJson (int options) const;
|
||||
virtual Json::Value getJson (int options, bool binary) const;
|
||||
|
||||
void sign (const RippleAddress & naAccountPrivate);
|
||||
bool checkSign (const RippleAddress & naAccountPublic) const;
|
||||
bool checkSign () const;
|
||||
bool isKnownGood () const
|
||||
{
|
||||
return mSigGood;
|
||||
}
|
||||
bool isKnownBad () const
|
||||
{
|
||||
return mSigBad;
|
||||
}
|
||||
void setGood () const
|
||||
{
|
||||
mSigGood = true;
|
||||
}
|
||||
void setBad () const
|
||||
{
|
||||
mSigBad = true;
|
||||
}
|
||||
|
||||
// SQL Functions
|
||||
static std::string getSQLValueHeader ();
|
||||
static std::string getSQLInsertHeader ();
|
||||
static std::string getSQLInsertIgnoreHeader ();
|
||||
std::string getSQL (std::string & sql, std::uint32_t inLedger, char status) const;
|
||||
std::string getSQL (std::uint32_t inLedger, char status) const;
|
||||
std::string getSQL (Serializer rawTxn, std::uint32_t inLedger, char status) const;
|
||||
|
||||
// SQL Functions with metadata
|
||||
static std::string getMetaSQLValueHeader ();
|
||||
static std::string getMetaSQLInsertReplaceHeader ();
|
||||
std::string getMetaSQL (std::uint32_t inLedger, const std::string & escapedMetaData) const;
|
||||
std::string getMetaSQL (Serializer rawTxn, std::uint32_t inLedger, char status, const std::string & escapedMetaData) const;
|
||||
|
||||
private:
|
||||
TxType mType;
|
||||
TxFormats::Item const* mFormat;
|
||||
|
||||
SerializedTransaction* duplicate () const
|
||||
{
|
||||
return new SerializedTransaction (*this);
|
||||
}
|
||||
|
||||
mutable bool mSigGood;
|
||||
mutable bool mSigBad;
|
||||
};
|
||||
|
||||
bool passesLocalChecks (STObject const& st, std::string&);
|
||||
bool passesLocalChecks (STObject const& st);
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
478
src/ripple/module/app/misc/Validations.cpp
Normal file
478
src/ripple/module/app/misc/Validations.cpp
Normal file
@@ -0,0 +1,478 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class ValidationsImp;
|
||||
|
||||
SETUP_LOG (Validations)
|
||||
|
||||
typedef std::map<uint160, SerializedValidation::pointer>::value_type u160_val_pair;
|
||||
typedef boost::shared_ptr<ValidationSet> VSpointer;
|
||||
|
||||
class ValidationsImp : public Validations
|
||||
{
|
||||
private:
|
||||
typedef RippleMutex LockType;
|
||||
typedef std::lock_guard <LockType> ScopedLockType;
|
||||
typedef beast::GenericScopedUnlock <LockType> ScopedUnlockType;
|
||||
LockType mLock;
|
||||
|
||||
TaggedCache<uint256, ValidationSet> mValidations;
|
||||
ripple::unordered_map<uint160, SerializedValidation::pointer> mCurrentValidations;
|
||||
std::vector<SerializedValidation::pointer> mStaleValidations;
|
||||
|
||||
bool mWriting;
|
||||
|
||||
private:
|
||||
boost::shared_ptr<ValidationSet> findCreateSet (uint256 const& ledgerHash)
|
||||
{
|
||||
VSpointer j = mValidations.fetch (ledgerHash);
|
||||
|
||||
if (!j)
|
||||
{
|
||||
j = boost::make_shared<ValidationSet> ();
|
||||
mValidations.canonicalize (ledgerHash, j);
|
||||
}
|
||||
|
||||
return j;
|
||||
}
|
||||
|
||||
boost::shared_ptr<ValidationSet> findSet (uint256 const& ledgerHash)
|
||||
{
|
||||
return mValidations.fetch (ledgerHash);
|
||||
}
|
||||
|
||||
public:
|
||||
ValidationsImp ()
|
||||
: mValidations ("Validations", 128, 600, get_seconds_clock (),
|
||||
LogPartition::getJournal <TaggedCacheLog> ())
|
||||
, mWriting (false)
|
||||
{
|
||||
mStaleValidations.reserve (512);
|
||||
}
|
||||
|
||||
private:
|
||||
bool addValidation (SerializedValidation::ref val, const std::string& source)
|
||||
{
|
||||
RippleAddress signer = val->getSignerPublic ();
|
||||
bool isCurrent = false;
|
||||
|
||||
if (!val->isTrusted() && getApp().getUNL().nodeInUNL (signer))
|
||||
val->setTrusted();
|
||||
|
||||
std::uint32_t now = getApp().getOPs().getCloseTimeNC();
|
||||
std::uint32_t valClose = val->getSignTime();
|
||||
|
||||
if ((now > (valClose - LEDGER_EARLY_INTERVAL)) && (now < (valClose + LEDGER_VAL_INTERVAL)))
|
||||
isCurrent = true;
|
||||
else
|
||||
WriteLog (lsWARNING, Validations) << "Received stale validation now=" << now << ", close=" << valClose;
|
||||
|
||||
if (!val->isTrusted ())
|
||||
{
|
||||
WriteLog (lsDEBUG, Validations) << "Node " << signer.humanNodePublic () << " not in UNL st=" << val->getSignTime () <<
|
||||
", hash=" << val->getLedgerHash () << ", shash=" << val->getSigningHash () << " src=" << source;
|
||||
}
|
||||
|
||||
uint256 hash = val->getLedgerHash ();
|
||||
uint160 node = signer.getNodeID ();
|
||||
|
||||
if (val->isTrusted () && isCurrent)
|
||||
{
|
||||
ScopedLockType sl (mLock);
|
||||
|
||||
if (!findCreateSet (hash)->insert (std::make_pair (node, val)).second)
|
||||
return false;
|
||||
|
||||
auto it = mCurrentValidations.find (node);
|
||||
|
||||
if (it == mCurrentValidations.end ())
|
||||
{
|
||||
// No previous validation from this validator
|
||||
mCurrentValidations.emplace (node, val);
|
||||
}
|
||||
else if (!it->second)
|
||||
{
|
||||
// Previous validation has expired
|
||||
it->second = val;
|
||||
}
|
||||
else if (val->getSignTime () > it->second->getSignTime ())
|
||||
{
|
||||
// This is a newer validation
|
||||
val->setPreviousHash (it->second->getLedgerHash ());
|
||||
mStaleValidations.push_back (it->second);
|
||||
it->second = val;
|
||||
condWrite ();
|
||||
}
|
||||
else
|
||||
{
|
||||
// We already have a newer validation from this source
|
||||
isCurrent = false;
|
||||
}
|
||||
}
|
||||
|
||||
WriteLog (lsDEBUG, Validations) << "Val for " << hash << " from " << signer.humanNodePublic ()
|
||||
<< " added " << (val->isTrusted () ? "trusted/" : "UNtrusted/") << (isCurrent ? "current" : "stale");
|
||||
|
||||
if (val->isTrusted () && isCurrent)
|
||||
{
|
||||
getApp().getLedgerMaster ().checkAccept (hash, val->getFieldU32 (sfLedgerSequence));
|
||||
return true;
|
||||
}
|
||||
|
||||
// FIXME: This never forwards untrusted validations
|
||||
return false;
|
||||
}
|
||||
|
||||
void tune (int size, int age)
|
||||
{
|
||||
mValidations.setTargetSize (size);
|
||||
mValidations.setTargetAge (age);
|
||||
}
|
||||
|
||||
ValidationSet getValidations (uint256 const& ledger)
|
||||
{
|
||||
{
|
||||
ScopedLockType sl (mLock);
|
||||
VSpointer set = findSet (ledger);
|
||||
|
||||
if (set)
|
||||
return *set;
|
||||
}
|
||||
return ValidationSet ();
|
||||
}
|
||||
|
||||
void getValidationCount (uint256 const& ledger, bool currentOnly, int& trusted, int& untrusted)
|
||||
{
|
||||
trusted = untrusted = 0;
|
||||
ScopedLockType sl (mLock);
|
||||
VSpointer set = findSet (ledger);
|
||||
|
||||
if (set)
|
||||
{
|
||||
std::uint32_t now = getApp().getOPs ().getNetworkTimeNC ();
|
||||
BOOST_FOREACH (u160_val_pair & it, *set)
|
||||
{
|
||||
bool isTrusted = it.second->isTrusted ();
|
||||
|
||||
if (isTrusted && currentOnly)
|
||||
{
|
||||
std::uint32_t closeTime = it.second->getSignTime ();
|
||||
|
||||
if ((now < (closeTime - LEDGER_EARLY_INTERVAL)) || (now > (closeTime + LEDGER_VAL_INTERVAL)))
|
||||
isTrusted = false;
|
||||
else
|
||||
{
|
||||
WriteLog (lsTRACE, Validations) << "VC: Untrusted due to time " << ledger;
|
||||
}
|
||||
}
|
||||
|
||||
if (isTrusted)
|
||||
++trusted;
|
||||
else
|
||||
++untrusted;
|
||||
}
|
||||
}
|
||||
|
||||
WriteLog (lsTRACE, Validations) << "VC: " << ledger << "t:" << trusted << " u:" << untrusted;
|
||||
}
|
||||
|
||||
void getValidationTypes (uint256 const& ledger, int& full, int& partial)
|
||||
{
|
||||
full = partial = 0;
|
||||
ScopedLockType sl (mLock);
|
||||
VSpointer set = findSet (ledger);
|
||||
|
||||
if (set)
|
||||
{
|
||||
BOOST_FOREACH (u160_val_pair & it, *set)
|
||||
{
|
||||
if (it.second->isTrusted ())
|
||||
{
|
||||
if (it.second->isFull ())
|
||||
++full;
|
||||
else
|
||||
++partial;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WriteLog (lsTRACE, Validations) << "VC: " << ledger << "f:" << full << " p:" << partial;
|
||||
}
|
||||
|
||||
|
||||
int getTrustedValidationCount (uint256 const& ledger)
|
||||
{
|
||||
int trusted = 0;
|
||||
ScopedLockType sl (mLock);
|
||||
VSpointer set = findSet (ledger);
|
||||
|
||||
if (set)
|
||||
{
|
||||
BOOST_FOREACH (u160_val_pair & it, *set)
|
||||
{
|
||||
if (it.second->isTrusted ())
|
||||
++trusted;
|
||||
}
|
||||
}
|
||||
|
||||
return trusted;
|
||||
}
|
||||
|
||||
int getFeeAverage (uint256 const& ledger, std::uint64_t ref, std::uint64_t& fee)
|
||||
{
|
||||
int trusted = 0;
|
||||
fee = 0;
|
||||
|
||||
ScopedLockType sl (mLock);
|
||||
VSpointer set = findSet (ledger);
|
||||
|
||||
if (set)
|
||||
{
|
||||
BOOST_FOREACH (u160_val_pair & it, *set)
|
||||
{
|
||||
if (it.second->isTrusted ())
|
||||
{
|
||||
++trusted;
|
||||
if (it.second->isFieldPresent(sfLoadFee))
|
||||
fee += it.second->getFieldU32(sfLoadFee);
|
||||
else
|
||||
fee += ref;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (trusted == 0)
|
||||
fee = ref;
|
||||
else
|
||||
fee /= trusted;
|
||||
return trusted;
|
||||
}
|
||||
|
||||
int getNodesAfter (uint256 const& ledger)
|
||||
{
|
||||
// Number of trusted nodes that have moved past this ledger
|
||||
int count = 0;
|
||||
ScopedLockType sl (mLock);
|
||||
BOOST_FOREACH (u160_val_pair & it, mCurrentValidations)
|
||||
{
|
||||
if (it.second->isTrusted () && it.second->isPreviousHash (ledger))
|
||||
++count;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int getLoadRatio (bool overLoaded)
|
||||
{
|
||||
// how many trusted nodes are able to keep up, higher is better
|
||||
int goodNodes = overLoaded ? 1 : 0;
|
||||
int badNodes = overLoaded ? 0 : 1;
|
||||
{
|
||||
ScopedLockType sl (mLock);
|
||||
BOOST_FOREACH (u160_val_pair & it, mCurrentValidations)
|
||||
{
|
||||
if (it.second->isTrusted ())
|
||||
{
|
||||
if (it.second->isFull ())
|
||||
++goodNodes;
|
||||
else
|
||||
++badNodes;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (goodNodes * 100) / (goodNodes + badNodes);
|
||||
}
|
||||
|
||||
std::list<SerializedValidation::pointer> getCurrentTrustedValidations ()
|
||||
{
|
||||
std::uint32_t cutoff = getApp().getOPs ().getNetworkTimeNC () - LEDGER_VAL_INTERVAL;
|
||||
|
||||
std::list<SerializedValidation::pointer> ret;
|
||||
|
||||
ScopedLockType sl (mLock);
|
||||
ripple::unordered_map<uint160, SerializedValidation::pointer>::iterator it = mCurrentValidations.begin ();
|
||||
|
||||
while (it != mCurrentValidations.end ())
|
||||
{
|
||||
if (!it->second) // contains no record
|
||||
it = mCurrentValidations.erase (it);
|
||||
else if (it->second->getSignTime () < cutoff)
|
||||
{
|
||||
// contains a stale record
|
||||
mStaleValidations.push_back (it->second);
|
||||
it->second.reset ();
|
||||
condWrite ();
|
||||
it = mCurrentValidations.erase (it);
|
||||
}
|
||||
else
|
||||
{
|
||||
// contains a live record
|
||||
if (it->second->isTrusted ())
|
||||
ret.push_back (it->second);
|
||||
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ripple::unordered_map<uint256, currentValidationCount>
|
||||
getCurrentValidations (uint256 currentLedger, uint256 priorLedger)
|
||||
{
|
||||
std::uint32_t cutoff = getApp().getOPs ().getNetworkTimeNC () - LEDGER_VAL_INTERVAL;
|
||||
bool valCurrentLedger = currentLedger.isNonZero ();
|
||||
bool valPriorLedger = priorLedger.isNonZero ();
|
||||
|
||||
ripple::unordered_map<uint256, currentValidationCount> ret;
|
||||
|
||||
ScopedLockType sl (mLock);
|
||||
ripple::unordered_map<uint160, SerializedValidation::pointer>::iterator it = mCurrentValidations.begin ();
|
||||
|
||||
while (it != mCurrentValidations.end ())
|
||||
{
|
||||
if (!it->second) // contains no record
|
||||
it = mCurrentValidations.erase (it);
|
||||
else if (it->second->getSignTime () < cutoff)
|
||||
{
|
||||
// contains a stale record
|
||||
mStaleValidations.push_back (it->second);
|
||||
it->second.reset ();
|
||||
condWrite ();
|
||||
it = mCurrentValidations.erase (it);
|
||||
}
|
||||
else
|
||||
{
|
||||
// contains a live record
|
||||
bool countPreferred = valCurrentLedger && (it->second->getLedgerHash () == currentLedger);
|
||||
|
||||
if (!countPreferred && // allow up to one ledger slip in either direction
|
||||
((valCurrentLedger && it->second->isPreviousHash (currentLedger)) ||
|
||||
(valPriorLedger && (it->second->getLedgerHash () == priorLedger))))
|
||||
{
|
||||
countPreferred = true;
|
||||
WriteLog (lsTRACE, Validations) << "Counting for " << currentLedger << " not " << it->second->getLedgerHash ();
|
||||
}
|
||||
|
||||
currentValidationCount& p = countPreferred ? ret[currentLedger] : ret[it->second->getLedgerHash ()];
|
||||
++ (p.first);
|
||||
uint160 ni = it->second->getNodeID ();
|
||||
|
||||
if (ni > p.second)
|
||||
p.second = ni;
|
||||
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void flush ()
|
||||
{
|
||||
bool anyNew = false;
|
||||
|
||||
WriteLog (lsINFO, Validations) << "Flushing validations";
|
||||
ScopedLockType sl (mLock);
|
||||
BOOST_FOREACH (u160_val_pair & it, mCurrentValidations)
|
||||
{
|
||||
if (it.second)
|
||||
mStaleValidations.push_back (it.second);
|
||||
|
||||
anyNew = true;
|
||||
}
|
||||
mCurrentValidations.clear ();
|
||||
|
||||
if (anyNew)
|
||||
condWrite ();
|
||||
|
||||
while (mWriting)
|
||||
{
|
||||
ScopedUnlockType sul (mLock);
|
||||
boost::this_thread::sleep (boost::posix_time::milliseconds (100));
|
||||
}
|
||||
|
||||
WriteLog (lsDEBUG, Validations) << "Validations flushed";
|
||||
}
|
||||
|
||||
void condWrite ()
|
||||
{
|
||||
if (mWriting)
|
||||
return;
|
||||
|
||||
mWriting = true;
|
||||
getApp().getJobQueue ().addJob (jtWRITE, "Validations::doWrite",
|
||||
std::bind (&ValidationsImp::doWrite,
|
||||
this, std::placeholders::_1));
|
||||
}
|
||||
|
||||
void doWrite (Job&)
|
||||
{
|
||||
LoadEvent::autoptr event (getApp().getJobQueue ().getLoadEventAP (jtDISK, "ValidationWrite"));
|
||||
boost::format insVal ("INSERT INTO Validations "
|
||||
"(LedgerHash,NodePubKey,SignTime,RawData) VALUES ('%s','%s','%u',%s);");
|
||||
|
||||
ScopedLockType sl (mLock);
|
||||
assert (mWriting);
|
||||
|
||||
while (!mStaleValidations.empty ())
|
||||
{
|
||||
std::vector<SerializedValidation::pointer> vector;
|
||||
vector.reserve (512);
|
||||
mStaleValidations.swap (vector);
|
||||
|
||||
{
|
||||
ScopedUnlockType sul (mLock);
|
||||
{
|
||||
Database* db = getApp().getLedgerDB ()->getDB ();
|
||||
DeprecatedScopedLock dbl (getApp().getLedgerDB ()->getDBLock ());
|
||||
|
||||
Serializer s (1024);
|
||||
db->executeSQL ("BEGIN TRANSACTION;");
|
||||
BOOST_FOREACH (SerializedValidation::ref it, vector)
|
||||
{
|
||||
s.erase ();
|
||||
it->add (s);
|
||||
db->executeSQL (boost::str (
|
||||
insVal % to_string (it->getLedgerHash ()) %
|
||||
it->getSignerPublic ().humanNodePublic () %
|
||||
it->getSignTime () % sqlEscape (s.peekData ())));
|
||||
}
|
||||
db->executeSQL ("END TRANSACTION;");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mWriting = false;
|
||||
}
|
||||
|
||||
void sweep ()
|
||||
{
|
||||
ScopedLockType sl (mLock);
|
||||
mValidations.sweep ();
|
||||
}
|
||||
};
|
||||
|
||||
Validations* Validations::New ()
|
||||
{
|
||||
return new ValidationsImp;
|
||||
}
|
||||
|
||||
} // ripple
|
||||
65
src/ripple/module/app/misc/Validations.h
Normal file
65
src/ripple/module/app/misc/Validations.h
Normal file
@@ -0,0 +1,65 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_VALIDATIONS_H_INCLUDED
|
||||
#define RIPPLE_VALIDATIONS_H_INCLUDED
|
||||
|
||||
namespace ripple {
|
||||
|
||||
// VFALCO TODO rename and move these typedefs into the Validations interface
|
||||
typedef ripple::unordered_map<uint160, SerializedValidation::pointer> ValidationSet;
|
||||
typedef std::pair<int, uint160> currentValidationCount; // nodes validating and highest node ID validating
|
||||
|
||||
class Validations : beast::LeakChecked <Validations>
|
||||
{
|
||||
public:
|
||||
static Validations* New ();
|
||||
|
||||
virtual ~Validations () { }
|
||||
|
||||
virtual bool addValidation (SerializedValidation::ref, const std::string& source) = 0;
|
||||
|
||||
virtual ValidationSet getValidations (uint256 const& ledger) = 0;
|
||||
|
||||
virtual void getValidationCount (uint256 const& ledger, bool currentOnly, int& trusted, int& untrusted) = 0;
|
||||
virtual void getValidationTypes (uint256 const& ledger, int& full, int& partial) = 0;
|
||||
|
||||
virtual int getTrustedValidationCount (uint256 const& ledger) = 0;
|
||||
|
||||
virtual int getFeeAverage(uint256 const& ledger, std::uint64_t ref, std::uint64_t& fee) = 0;
|
||||
|
||||
virtual int getNodesAfter (uint256 const& ledger) = 0;
|
||||
virtual int getLoadRatio (bool overLoaded) = 0;
|
||||
|
||||
// VFALCO TODO make a typedef for this ugly return value!
|
||||
virtual ripple::unordered_map<uint256, currentValidationCount> getCurrentValidations (
|
||||
uint256 currentLedger, uint256 previousLedger) = 0;
|
||||
|
||||
virtual std::list <SerializedValidation::pointer> getCurrentTrustedValidations () = 0;
|
||||
|
||||
virtual void tune (int size, int age) = 0;
|
||||
|
||||
virtual void flush () = 0;
|
||||
|
||||
virtual void sweep () = 0;
|
||||
};
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user