mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
Work in progress on ripple.
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/format.hpp>
|
||||
#include <queue>
|
||||
|
||||
#include "../json/writer.h"
|
||||
|
||||
@@ -17,7 +18,8 @@
|
||||
#include "utils.h"
|
||||
|
||||
// Small for testing, should likely be 32 or 64.
|
||||
#define DIR_NODE_MAX 2
|
||||
#define DIR_NODE_MAX 2
|
||||
#define RIPPLE_PATHS_MAX 3
|
||||
|
||||
bool transResultInfo(TransactionEngineResult terCode, std::string& strToken, std::string& strHuman)
|
||||
{
|
||||
@@ -33,6 +35,7 @@ bool transResultInfo(TransactionEngineResult terCode, std::string& strToken, std
|
||||
{ tenBAD_GEN_AUTH, "tenBAD_GEN_AUTH", "Not authorized to claim generator." },
|
||||
{ tenBAD_ISSUER, "tenBAD_ISSUER", "Malformed." },
|
||||
{ tenBAD_OFFER, "tenBAD_OFFER", "Malformed." },
|
||||
{ tenBAD_PATH_COUNT, "tenBAD_PATH_COUNT", "Malformed: too many paths." },
|
||||
{ tenBAD_RIPPLE, "tenBAD_RIPPLE", "Ledger prevents ripple from succeeding." },
|
||||
{ tenBAD_SET_ID, "tenBAD_SET_ID", "Malformed." },
|
||||
{ tenCLAIMED, "tenCLAIMED", "Can not claim a previously claimed account." },
|
||||
@@ -72,6 +75,8 @@ bool transResultInfo(TransactionEngineResult terCode, std::string& strToken, std
|
||||
{ terOVER_LIMIT, "terOVER_LIMIT", "Over limit." },
|
||||
{ terPAST_LEDGER, "terPAST_LEDGER", "The transaction expired and can't be applied" },
|
||||
{ terPAST_SEQ, "terPAST_SEQ", "This sequence number has already past" },
|
||||
{ terPATH_EMPTY, "terPATH_EMPTY", "Path could not send partial amount." },
|
||||
{ terPATH_PARTIAL, "terPATH_PARTIAL", "Path could not send full amount." },
|
||||
{ terPRE_SEQ, "terPRE_SEQ", "Missing/inapplicable prior transaction" },
|
||||
{ terSET_MISSING_DST, "terSET_MISSING_DST", "Can't set password, destination missing." },
|
||||
{ terSUCCESS, "terSUCCESS", "The transaction was applied" },
|
||||
@@ -2126,6 +2131,44 @@ bool calcPaymentForward(std::vector<paymentNode>& pnNodes)
|
||||
}
|
||||
#endif
|
||||
|
||||
// Ensure sort order is complelely deterministic.
|
||||
class PathStateCompare
|
||||
{
|
||||
public:
|
||||
bool operator()(const PathState::pointer& lhs, const PathState::pointer& rhs)
|
||||
{
|
||||
// Return true, iff lhs has less priority than rhs.
|
||||
|
||||
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.
|
||||
|
||||
// Path index is third rank.
|
||||
return lhs->mIndex > rhs->mIndex; // Bigger is worse.
|
||||
}
|
||||
};
|
||||
|
||||
PathState::pointer TransactionEngine::pathCreate(const STPath& spPath)
|
||||
{
|
||||
return PathState::pointer();
|
||||
}
|
||||
|
||||
// Calcuate 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)
|
||||
{
|
||||
@@ -2313,47 +2356,72 @@ TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction
|
||||
STPathSet spsPaths = txn.getITFieldPathSet(sfPaths);
|
||||
|
||||
// XXX If we are parsing for determing forwarding check maximum path count.
|
||||
if (!spsPaths.getPathCount())
|
||||
if (!spsPaths.isEmpty())
|
||||
{
|
||||
Log(lsINFO) << "doPayment: Invalid transaction: No paths.";
|
||||
|
||||
return tenRIPPLE_EMPTY;
|
||||
}
|
||||
#if 0
|
||||
// 1) Calc payment in reverse: do not modify sles.
|
||||
// 2) Calc payment forward: do modify sles.
|
||||
std::vector<STPath> spPath;
|
||||
|
||||
BOOST_FOREACH(std::vector<STPath>& spPath, spsPaths)
|
||||
else if (spsPaths.getPathCount() > RIPPLE_PATHS_MAX)
|
||||
{
|
||||
return tenBAD_PATH_COUNT;
|
||||
}
|
||||
|
||||
Log(lsINFO) << "doPayment: Implementation error: Not implemented.";
|
||||
// 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);
|
||||
|
||||
return tenUNKNOWN;
|
||||
pqPaths.push(pspCur);
|
||||
}
|
||||
#endif
|
||||
TransactionEngineResult terResult;
|
||||
STAmount saPaid;
|
||||
STAmount saWanted;
|
||||
uint32 uFlags = txn.getFlags(); // XXX Redundant.
|
||||
|
||||
#if 0
|
||||
// XXX Or additionally queue unfundeds for removal on failure.
|
||||
if (terSUCCESS == terResult)
|
||||
terResult = tenUNKNOWN;
|
||||
while (tenUNKNOWN == terResult)
|
||||
{
|
||||
// Transaction failed. Process possible unfunded offers.
|
||||
entryReset(txn);
|
||||
|
||||
BOOST_FOREACH(const uint256& uOfferIndex, mUnfunded)
|
||||
if (!pqPaths.empty())
|
||||
{
|
||||
SLE::pointer sleOffer = mLedger->getOffer(uOfferIndex);
|
||||
uint160 uOfferID = sleOffer->getIValueFieldAccount(sfAccount).getAccountID();
|
||||
STAmount saOfferFunds = sleOffer->getIValueFieldAmount(sfTakerGets);
|
||||
// Have a path to contribute.
|
||||
PathState::pointer pspCur = pqPaths.top();
|
||||
|
||||
if (!accountFunds(uOfferID, saOfferFunds).isPositive())
|
||||
pqPaths.pop();
|
||||
|
||||
pathApply(pspCur);
|
||||
|
||||
if (tenUNKNOWN == terResult && saPaid == saWanted)
|
||||
{
|
||||
offerDelete(sleOffer, uOfferIndex, uOfferID);
|
||||
bWrite = true;
|
||||
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))
|
||||
{
|
||||
// Partial payment not allowed.
|
||||
terResult = terPATH_PARTIAL; // XXX No effect, except unfunded and charge fee.
|
||||
}
|
||||
else if (saPaid.isZero())
|
||||
{
|
||||
// Nothing claimed.
|
||||
terResult = terPATH_EMPTY; // XXX No effect except unfundeds and charge fee.
|
||||
// XXX
|
||||
}
|
||||
else
|
||||
{
|
||||
terResult = terSUCCESS;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
Log(lsINFO) << "doPayment: Delay transaction: No ripple paths could be satisfied.";
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ enum TransactionEngineResult
|
||||
tenBAD_GEN_AUTH,
|
||||
tenBAD_ISSUER,
|
||||
tenBAD_OFFER,
|
||||
tenBAD_PATH_COUNT,
|
||||
tenBAD_SET_ID,
|
||||
tenCREATEXNS,
|
||||
tenDST_IS_SRC,
|
||||
@@ -78,6 +79,11 @@ enum TransactionEngineResult
|
||||
terSET_MISSING_DST,
|
||||
terUNCLAIMED,
|
||||
terUNFUNDED,
|
||||
|
||||
// Might succeed in different order.
|
||||
// XXX claim fee and try to delete unfunded.
|
||||
terPATH_EMPTY,
|
||||
terPATH_PARTIAL,
|
||||
};
|
||||
|
||||
bool transResultInfo(TransactionEngineResult terCode, std::string& strToken, std::string& strHuman);
|
||||
@@ -102,6 +108,22 @@ enum TransactionAccountAction
|
||||
|
||||
typedef std::pair<TransactionAccountAction, SerializedLedgerEntry::pointer> AffectedAccount;
|
||||
|
||||
// Hold a path state under incremental application.
|
||||
class PathState
|
||||
{
|
||||
public:
|
||||
typedef boost::shared_ptr<PathState> pointer;
|
||||
|
||||
int mIndex;
|
||||
uint64 uQuality; // 0 = none.
|
||||
STAmount saIn;
|
||||
STAmount saOut;
|
||||
|
||||
PathState(int iIndex) : mIndex(iIndex) { ; };
|
||||
|
||||
static PathState::pointer createPathState(int iIndex) { return boost::make_shared<PathState>(iIndex); };
|
||||
};
|
||||
|
||||
// One instance per ledger.
|
||||
// Only one transaction applied at a time.
|
||||
class TransactionEngine
|
||||
@@ -190,6 +212,10 @@ protected:
|
||||
STAmount accountSend(const uint160& uSenderID, const uint160& uReceiverID, const STAmount& saAmount);
|
||||
STAmount accountFunds(const uint160& uAccountID, const STAmount& saDefault);
|
||||
|
||||
PathState::pointer pathCreate(const STPath& spPath);
|
||||
void pathApply(PathState::pointer pspCur);
|
||||
void pathNext(PathState::pointer pspCur);
|
||||
|
||||
void txnWrite();
|
||||
|
||||
TransactionEngineResult offerDelete(const SLE::pointer& sleOffer, const uint256& uOfferIndex, const uint160& uOwnerID);
|
||||
|
||||
@@ -35,15 +35,22 @@ const int TransactionIFee = 4;
|
||||
const int TransactionMinLen = 32;
|
||||
const int TransactionMaxLen = 1048576;
|
||||
|
||||
//
|
||||
// Transaction flags.
|
||||
const uint32 tfCreateAccount = 0x00010000;
|
||||
const uint32 tfNoRippleDirect = 0x00020000;
|
||||
|
||||
const uint32 tfPassive = 0x00010000;
|
||||
//
|
||||
|
||||
// AccountSet flags:
|
||||
const uint32 tfUnsetEmailHash = 0x00010000;
|
||||
const uint32 tfUnsetWalletLocator = 0x00020000;
|
||||
|
||||
// OfferCreate flags:
|
||||
const uint32 tfPassive = 0x00010000;
|
||||
|
||||
// Payment flags:
|
||||
const uint32 tfCreateAccount = 0x00010000;
|
||||
const uint32 tfPartialPayment = 0x00020000;
|
||||
const uint32 tfNoRippleDirect = 0x00040000;
|
||||
|
||||
extern TransactionFormat InnerTxnFormats[];
|
||||
extern TransactionFormat* getTxnFormat(TransactionType t);
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user