mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Work towards ripple.
This commit is contained in:
@@ -15,7 +15,7 @@ void LedgerEntrySet::clear()
|
||||
mSet.clear();
|
||||
}
|
||||
|
||||
LedgerEntrySet LedgerEntrySet::duplicate()
|
||||
LedgerEntrySet LedgerEntrySet::duplicate() const
|
||||
{
|
||||
return LedgerEntrySet(mEntries, mSet, mSeq + 1);
|
||||
}
|
||||
@@ -180,4 +180,9 @@ void LedgerEntrySet::entryDelete(SLE::pointer& sle)
|
||||
}
|
||||
}
|
||||
|
||||
bool LedgerEntrySet::intersect(const LedgerEntrySet& lesLeft, const LedgerEntrySet& lesRight)
|
||||
{
|
||||
return true; // XXX Needs implementation
|
||||
}
|
||||
|
||||
// vim:ts=4
|
||||
|
||||
@@ -34,14 +34,14 @@ protected:
|
||||
TransactionMetaSet mSet;
|
||||
int mSeq;
|
||||
|
||||
LedgerEntrySet(const boost::unordered_map<uint256, LedgerEntrySetEntry> &e, TransactionMetaSet& s, int m) :
|
||||
LedgerEntrySet(const boost::unordered_map<uint256, LedgerEntrySetEntry> &e, const TransactionMetaSet& s, int m) :
|
||||
mEntries(e), mSet(s), mSeq(m) { ; }
|
||||
|
||||
public:
|
||||
LedgerEntrySet() : mSeq(0) { ; }
|
||||
|
||||
// set functions
|
||||
LedgerEntrySet duplicate(); // Make a duplicate of this set
|
||||
LedgerEntrySet duplicate() const; // Make a duplicate of this set
|
||||
void setTo(LedgerEntrySet&); // Set this set to have the same contents as another
|
||||
void swapWith(LedgerEntrySet&); // Swap the contents of two sets
|
||||
|
||||
@@ -64,6 +64,8 @@ public:
|
||||
boost::unordered_map<uint256, LedgerEntrySetEntry>::const_iterator end() const { return mEntries.end(); }
|
||||
boost::unordered_map<uint256, LedgerEntrySetEntry>::iterator begin() { return mEntries.begin(); }
|
||||
boost::unordered_map<uint256, LedgerEntrySetEntry>::iterator end() { return mEntries.end(); }
|
||||
|
||||
static bool intersect(const LedgerEntrySet& lesLeft, const LedgerEntrySet& lesRight);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -464,13 +464,13 @@ void STPathSet::add(Serializer& s) const
|
||||
|
||||
s.add8(iType);
|
||||
|
||||
if (iType && STPathElement::typeAccount)
|
||||
if (iType & STPathElement::typeAccount)
|
||||
s.add160(speElement.getAccountID());
|
||||
|
||||
if (iType && STPathElement::typeCurrency)
|
||||
if (iType & STPathElement::typeCurrency)
|
||||
s.add160(speElement.getCurrency());
|
||||
|
||||
if (iType && STPathElement::typeIssuer)
|
||||
if (iType & STPathElement::typeIssuer)
|
||||
s.add160(speElement.getIssuerID());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2161,51 +2161,67 @@ bool calcPaymentForward(std::vector<paymentNode>& pnNodes)
|
||||
}
|
||||
#endif
|
||||
|
||||
// Ensure sort order is complelely deterministic.
|
||||
class PathStateCompare
|
||||
bool PathState::less(const PathState::pointer& lhs, const PathState::pointer& rhs)
|
||||
{
|
||||
public:
|
||||
bool operator()(const PathState::pointer& lhs, const PathState::pointer& rhs)
|
||||
{
|
||||
// Return true, iff lhs has less priority than rhs.
|
||||
// Return true, iff lhs has less priority than rhs.
|
||||
|
||||
if (lhs->uQuality != rhs->uQuality)
|
||||
return lhs->uQuality > rhs->uQuality; // Bigger is worse.
|
||||
if (lhs->uQuality != rhs->uQuality)
|
||||
return lhs->uQuality > rhs->uQuality; // Bigger is worse.
|
||||
|
||||
// Best quanity is second rank.
|
||||
if (lhs->saOut != rhs->saOut)
|
||||
return lhs->saOut < rhs->saOut; // Smaller is worse.
|
||||
// Best quanity is second rank.
|
||||
if (lhs->saOut != rhs->saOut)
|
||||
return lhs->saOut < rhs->saOut; // Smaller is worse.
|
||||
|
||||
// Path index is third rank.
|
||||
return lhs->mIndex > rhs->mIndex; // Bigger is worse.
|
||||
}
|
||||
};
|
||||
|
||||
PathState::pointer TransactionEngine::pathCreate(const STPath& spPath)
|
||||
{
|
||||
return PathState::pointer();
|
||||
// Path index is third rank.
|
||||
return lhs->mIndex > rhs->mIndex; // Bigger is worse.
|
||||
}
|
||||
|
||||
// Calcuate the next increment of a path.
|
||||
PathState::PathState(
|
||||
int iIndex,
|
||||
const LedgerEntrySet& lesSource,
|
||||
const STPath& spSourcePath,
|
||||
uint160 uReceiverID,
|
||||
uint160 uSenderID,
|
||||
STAmount saSend,
|
||||
STAmount saSendMax,
|
||||
bool bPartialPayment
|
||||
)
|
||||
: mIndex(iIndex), uQuality(0), bDirty(true)
|
||||
{
|
||||
lesEntries = lesSource.duplicate();
|
||||
|
||||
paymentNode pnFirst;
|
||||
paymentNode pnLast;
|
||||
|
||||
pnLast.bPartialPayment = bPartialPayment;
|
||||
pnLast.uAccount = uReceiverID;
|
||||
pnLast.saWanted = saSend;
|
||||
|
||||
pnFirst.uAccount = uSenderID;
|
||||
pnFirst.saWanted = saSendMax;
|
||||
|
||||
vpnNodes.push_back(pnFirst);
|
||||
vpnNodes.push_back(pnLast);
|
||||
}
|
||||
|
||||
// Calculate the next increment of a path.
|
||||
void TransactionEngine::pathNext(PathState::pointer pspCur)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Apply an increment of the path, then calculate the next increment.
|
||||
void TransactionEngine::pathApply(PathState::pointer pspCur)
|
||||
{
|
||||
|
||||
pathNext(pspCur);
|
||||
}
|
||||
|
||||
// XXX Need to audit for things like setting accountID not having memory.
|
||||
TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction& txn)
|
||||
{
|
||||
// Ripple if source or destination is non-native or if there are paths.
|
||||
uint32 txFlags = txn.getFlags();
|
||||
bool bCreate = !!(txFlags & tfCreateAccount);
|
||||
bool bNoRippleDirect = !!(txFlags & tfNoRippleDirect);
|
||||
uint32 uTxFlags = txn.getFlags();
|
||||
bool bCreate = !!(uTxFlags & tfCreateAccount);
|
||||
bool bNoRippleDirect = !!(uTxFlags & tfNoRippleDirect);
|
||||
bool bPartialPayment = !!(uTxFlags & tfPartialPayment);
|
||||
bool bPaths = txn.getITFieldPresent(sfPaths);
|
||||
bool bMax = txn.getITFieldPresent(sfSendMax);
|
||||
uint160 uDstAccountID = txn.getITFieldAccount(sfDestination);
|
||||
@@ -2385,7 +2401,6 @@ TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction
|
||||
|
||||
STPathSet spsPaths = txn.getITFieldPathSet(sfPaths);
|
||||
|
||||
// XXX If we are parsing for determing forwarding check maximum path count.
|
||||
if (!spsPaths.isEmpty())
|
||||
{
|
||||
Log(lsINFO) << "doPayment: Invalid transaction: No paths.";
|
||||
@@ -2398,45 +2413,80 @@ TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction
|
||||
}
|
||||
|
||||
// Incrementally search paths.
|
||||
std::priority_queue<PathState::pointer, std::vector<PathState::pointer>, PathStateCompare> pqPaths;
|
||||
#if 0
|
||||
BOOST_FOREACH(std::vector<STPath>::const_iterator::value_type spPath, spsPaths)
|
||||
{
|
||||
PathState::pointer pspCur = pathCreate(spPath);
|
||||
std::vector<PathState::pointer> vpsPaths;
|
||||
|
||||
pqPaths.push(pspCur);
|
||||
BOOST_FOREACH(const STPath& spPath, spsPaths)
|
||||
{
|
||||
vpsPaths.push_back(PathState::createPathState(
|
||||
vpsPaths.size(),
|
||||
mNodes,
|
||||
spPath,
|
||||
uDstAccountID,
|
||||
mTxnAccountID,
|
||||
saDstAmount,
|
||||
saMaxAmount,
|
||||
bPartialPayment
|
||||
));
|
||||
}
|
||||
#endif
|
||||
|
||||
TransactionEngineResult terResult;
|
||||
STAmount saPaid;
|
||||
STAmount saWanted;
|
||||
uint32 uFlags = txn.getFlags(); // XXX Redundant.
|
||||
|
||||
terResult = tenUNKNOWN;
|
||||
while (tenUNKNOWN == terResult)
|
||||
{
|
||||
if (!pqPaths.empty())
|
||||
PathState::pointer pspBest;
|
||||
|
||||
// Find the best path.
|
||||
BOOST_FOREACH(PathState::pointer pspCur, vpsPaths)
|
||||
{
|
||||
// Have a path to contribute.
|
||||
PathState::pointer pspCur = pqPaths.top();
|
||||
if (pspCur->bDirty)
|
||||
{
|
||||
pspCur->bDirty = false;
|
||||
pspCur->lesEntries = mNodes.duplicate();
|
||||
|
||||
pqPaths.pop();
|
||||
// XXX Compute increment
|
||||
pathNext(pspCur);
|
||||
}
|
||||
|
||||
pathApply(pspCur);
|
||||
if (!pspBest || (pspCur->uQuality && PathState::less(pspBest, pspCur)))
|
||||
pspBest = pspCur;
|
||||
}
|
||||
|
||||
if (!pspBest)
|
||||
{
|
||||
//
|
||||
// Apply path.
|
||||
//
|
||||
|
||||
// Install changes for path.
|
||||
mNodes.swapWith(pspBest->lesEntries);
|
||||
|
||||
// Mark that path as dirty.
|
||||
pspBest->bDirty = true;
|
||||
|
||||
// Mark as dirty any other path that intersected.
|
||||
BOOST_FOREACH(PathState::pointer& pspOther, vpsPaths)
|
||||
{
|
||||
// Look for intersection of best and the others.
|
||||
// - Will forget the intersection applied.
|
||||
// - Anything left will not interfere with it.
|
||||
// - Will remember the non-intersection non-applied for future consideration.
|
||||
if (!pspOther->bDirty
|
||||
&& pspOther->uQuality
|
||||
&& LedgerEntrySet::intersect(pspBest->lesEntries, pspOther->lesEntries))
|
||||
pspOther->bDirty = true;
|
||||
}
|
||||
|
||||
// Figure out if done.
|
||||
if (tenUNKNOWN == terResult && saPaid == saWanted)
|
||||
{
|
||||
terResult = terSUCCESS;
|
||||
}
|
||||
|
||||
if (tenUNKNOWN == terResult && pspCur->uQuality)
|
||||
{
|
||||
// Current path still has something to contribute.
|
||||
pqPaths.push(pspCur);
|
||||
}
|
||||
}
|
||||
// Ran out of paths.
|
||||
else if ((!uFlags & tfPartialPayment))
|
||||
else if (!bPartialPayment)
|
||||
{
|
||||
// Partial payment not allowed.
|
||||
terResult = terPATH_PARTIAL; // XXX No effect, except unfunded and charge fee.
|
||||
|
||||
@@ -105,14 +105,60 @@ class PathState
|
||||
public:
|
||||
typedef boost::shared_ptr<PathState> pointer;
|
||||
|
||||
int mIndex;
|
||||
uint64 uQuality; // 0 = none.
|
||||
STAmount saIn;
|
||||
STAmount saOut;
|
||||
typedef struct {
|
||||
bool bPartialPayment; // -->
|
||||
uint16 uFlags; // --> from path
|
||||
|
||||
PathState(int iIndex) : mIndex(iIndex) { ; };
|
||||
uint160 uAccount; // --> recieving/sending account
|
||||
|
||||
static PathState::pointer createPathState(int iIndex) { return boost::make_shared<PathState>(iIndex); };
|
||||
STAmount saWanted; // --> What this node wants from upstream.
|
||||
|
||||
// Maybe this should just be a bool:
|
||||
// STAmount saIOURedeemMax; // --> Max amount of IOUs to redeem downstream.
|
||||
// Maybe this should just be a bool:
|
||||
// STAmount saIOUIssueMax; // --> Max Amount of IOUs to issue downstream.
|
||||
|
||||
STAmount saIOURedeem; // <-- What this node will redeem downstream.
|
||||
STAmount saIOUIssue; // <-- What this node will issue downstream.
|
||||
STAmount saSend; // <-- Stamps this node will send downstream.
|
||||
|
||||
STAmount saRecieve; // Amount stamps to receive.
|
||||
|
||||
} paymentNode;
|
||||
|
||||
std::vector<paymentNode> vpnNodes;
|
||||
LedgerEntrySet lesEntries;
|
||||
|
||||
int mIndex;
|
||||
uint64 uQuality; // 0 = none.
|
||||
STAmount saIn;
|
||||
STAmount saOut;
|
||||
bool bDirty; // Path not computed.
|
||||
|
||||
PathState(
|
||||
int iIndex,
|
||||
const LedgerEntrySet& lesSource,
|
||||
const STPath& spSourcePath,
|
||||
uint160 uReceiverID,
|
||||
uint160 uSenderID,
|
||||
STAmount saSend,
|
||||
STAmount saSendMax,
|
||||
bool bPartialPayment
|
||||
);
|
||||
|
||||
static PathState::pointer createPathState(
|
||||
int iIndex,
|
||||
const LedgerEntrySet& lesSource,
|
||||
const STPath& spSourcePath,
|
||||
uint160 uReceiverID,
|
||||
uint160 uSenderID,
|
||||
STAmount saSend,
|
||||
STAmount saSendMax,
|
||||
bool bPartialPayment
|
||||
)
|
||||
{ return boost::make_shared<PathState>(iIndex, lesSource, spSourcePath, uReceiverID, uSenderID, saSend, saSendMax, bPartialPayment); };
|
||||
|
||||
static bool less(const PathState::pointer& lhs, const PathState::pointer& rhs);
|
||||
};
|
||||
|
||||
// One instance per ledger.
|
||||
@@ -137,25 +183,6 @@ private:
|
||||
bool dirNext(const uint256& uRootIndex, SLE::pointer& sleNode, unsigned int& uDirEntry, uint256& uEntryIndex);
|
||||
|
||||
#ifdef WORK_IN_PROGRESS
|
||||
typedef struct {
|
||||
uint16 uFlags; // --> from path
|
||||
|
||||
STAccount saAccount; // --> recieving/sending account
|
||||
|
||||
STAmount saWanted; // --> What this node wants from upstream.
|
||||
|
||||
// Maybe this should just be a bool:
|
||||
STAmount saIOURedeemMax; // --> Max amount of IOUs to redeem downstream.
|
||||
// Maybe this should just be a bool:
|
||||
STAmount saIOUIssueMax; // --> Max Amount of IOUs to issue downstream.
|
||||
|
||||
STAmount saIOURedeem; // <-- What this node will redeem downstream.
|
||||
STAmount saIOUIssue; // <-- What this node will issue downstream.
|
||||
STAmount saSend; // <-- Stamps this node will send downstream.
|
||||
|
||||
STAmount saRecieve; // Amount stamps to receive.
|
||||
|
||||
} paymentNode;
|
||||
|
||||
typedef struct {
|
||||
std::vector<paymentNode> vpnNodes;
|
||||
|
||||
Reference in New Issue
Block a user