Merge branch 'master' of github.com:jedmccaleb/NewCoin

This commit is contained in:
JoelKatz
2012-08-29 14:40:00 -07:00
7 changed files with 287 additions and 203 deletions

View File

@@ -534,6 +534,7 @@ void LedgerConsensus::updateOurPositions()
}
std::map<uint32, int> closeTimes;
BOOST_FOREACH(u160_prop_pair& it, mPeerPositions)
++closeTimes[it.second->getCloseTime() - (it.second->getCloseTime() % mCloseResolution)];
@@ -803,7 +804,7 @@ void LedgerConsensus::applyTransaction(TransactionEngine& engine, const Serializ
try
{
#endif
TransactionEngineResult result = engine.applyTransaction(*txn, parms);
TER result = engine.applyTransaction(*txn, parms);
if (result > 0)
{
Log(lsINFO) << " retry";
@@ -865,7 +866,7 @@ void LedgerConsensus::applyTransactions(const SHAMap::pointer& set, const Ledger
{
try
{
TransactionEngineResult result = engine.applyTransaction(*it->second, parms);
TER result = engine.applyTransaction(*it->second, parms);
if (result <= 0)
{
if (result == 0) ++successes;

View File

@@ -80,10 +80,10 @@ Ledger::pointer LedgerMaster::closeLedger()
return closingLedger;
}
TransactionEngineResult LedgerMaster::doTransaction(const SerializedTransaction& txn, uint32 targetLedger,
TER LedgerMaster::doTransaction(const SerializedTransaction& txn, uint32 targetLedger,
TransactionEngineParams params)
{
TransactionEngineResult result = mEngine.applyTransaction(txn, params);
TER result = mEngine.applyTransaction(txn, params);
theApp->getOPs().pubTransaction(mEngine.getLedger(), txn, result);
return result;
}

View File

@@ -45,7 +45,7 @@ public:
void runStandAlone() { mFinalizedLedger = mCurrentLedger; }
TransactionEngineResult doTransaction(const SerializedTransaction& txn, uint32 targetLedger,
TER doTransaction(const SerializedTransaction& txn, uint32 targetLedger,
TransactionEngineParams params);
void pushLedger(const Ledger::pointer& newLedger);

View File

@@ -84,7 +84,7 @@ Transaction::pointer NetworkOPs::processTransaction(Transaction::pointer trans,
return trans;
}
TransactionEngineResult r = mLedgerMaster->doTransaction(*trans->getSTransaction(), tgtLedger, tepNONE);
TER r = mLedgerMaster->doTransaction(*trans->getSTransaction(), tgtLedger, tepNONE);
if (r == tefFAILURE) throw Fault(IO_ERROR);
if (r == terPRE_SEQ)
@@ -882,7 +882,7 @@ void NetworkOPs::pubLedger(const Ledger::pointer& lpAccepted)
SerializedTransaction::pointer stTxn = theApp->getMasterTransaction().fetch(item, false, 0);
// XXX Need to support other results.
// XXX Need to give failures too.
TransactionEngineResult terResult = tesSUCCESS;
TER terResult = tesSUCCESS;
if (bAll)
{
@@ -916,7 +916,7 @@ void NetworkOPs::pubLedger(const Ledger::pointer& lpAccepted)
// XXX Publish delta information for accounts.
}
Json::Value NetworkOPs::transJson(const SerializedTransaction& stTxn, TransactionEngineResult terResult, const std::string& strStatus, int iSeq, const std::string& strType)
Json::Value NetworkOPs::transJson(const SerializedTransaction& stTxn, TER terResult, const std::string& strStatus, int iSeq, const std::string& strType)
{
Json::Value jvObj(Json::objectValue);
std::string strToken;
@@ -934,7 +934,7 @@ Json::Value NetworkOPs::transJson(const SerializedTransaction& stTxn, Transactio
return jvObj;
}
void NetworkOPs::pubTransactionAll(const Ledger::pointer& lpCurrent, const SerializedTransaction& stTxn, TransactionEngineResult terResult, const char* pState)
void NetworkOPs::pubTransactionAll(const Ledger::pointer& lpCurrent, const SerializedTransaction& stTxn, TER terResult, const char* pState)
{
Json::Value jvObj = transJson(stTxn, terResult, pState, lpCurrent->getLedgerSeq(), "transaction");
@@ -944,7 +944,7 @@ void NetworkOPs::pubTransactionAll(const Ledger::pointer& lpCurrent, const Seria
}
}
void NetworkOPs::pubTransactionAccounts(const Ledger::pointer& lpCurrent, const SerializedTransaction& stTxn, TransactionEngineResult terResult, const char* pState)
void NetworkOPs::pubTransactionAccounts(const Ledger::pointer& lpCurrent, const SerializedTransaction& stTxn, TER terResult, const char* pState)
{
boost::unordered_set<InfoSub*> usisNotify;
@@ -979,7 +979,7 @@ void NetworkOPs::pubTransactionAccounts(const Ledger::pointer& lpCurrent, const
}
}
void NetworkOPs::pubTransaction(const Ledger::pointer& lpCurrent, const SerializedTransaction& stTxn, TransactionEngineResult terResult)
void NetworkOPs::pubTransaction(const Ledger::pointer& lpCurrent, const SerializedTransaction& stTxn, TER terResult)
{
boost::interprocess::sharable_lock<boost::interprocess::interprocess_upgradable_mutex> sl(mMonitorLock);

View File

@@ -77,9 +77,9 @@ protected:
void setMode(OperatingMode);
Json::Value transJson(const SerializedTransaction& stTxn, TransactionEngineResult terResult, const std::string& strStatus, int iSeq, const std::string& strType);
void pubTransactionAll(const Ledger::pointer& lpCurrent, const SerializedTransaction& stTxn, TransactionEngineResult terResult, const char* pState);
void pubTransactionAccounts(const Ledger::pointer& lpCurrent, const SerializedTransaction& stTxn, TransactionEngineResult terResult, const char* pState);
Json::Value transJson(const SerializedTransaction& stTxn, TER terResult, const std::string& strStatus, int iSeq, const std::string& strType);
void pubTransactionAll(const Ledger::pointer& lpCurrent, const SerializedTransaction& stTxn, TER terResult, const char* pState);
void pubTransactionAccounts(const Ledger::pointer& lpCurrent, const SerializedTransaction& stTxn, TER terResult, const char* pState);
Json::Value pubBootstrapAccountInfo(const Ledger::pointer& lpAccepted, const NewcoinAddress& naAccountID);
@@ -195,7 +195,7 @@ public:
void pubAccountInfo(const NewcoinAddress& naAccountID, const Json::Value& jvObj);
void pubLedger(const Ledger::pointer& lpAccepted);
void pubTransaction(const Ledger::pointer& lpLedger, const SerializedTransaction& stTxn, TransactionEngineResult terResult);
void pubTransaction(const Ledger::pointer& lpLedger, const SerializedTransaction& stTxn, TER terResult);
//
// Monitoring: subscriber side

View File

@@ -36,12 +36,12 @@ std::size_t hash_value(const aciSource& asValue)
return seed;
}
bool transResultInfo(TransactionEngineResult terCode, std::string& strToken, std::string& strHuman)
bool transResultInfo(TER terCode, std::string& strToken, std::string& strHuman)
{
static struct {
TransactionEngineResult terCode;
const char* cpToken;
const char* cpHuman;
TER terCode;
const char* cpToken;
const char* cpHuman;
} transResultInfoA[] = {
{ tefALREADY, "tefALREADY", "The exact transaction was already in this ledger" },
{ tefBAD_ADD_AUTH, "tefBAD_ADD_AUTH", "Not authorized to add account." },
@@ -50,6 +50,7 @@ bool transResultInfo(TransactionEngineResult terCode, std::string& strToken, std
{ tefBAD_GEN_AUTH, "tefBAD_GEN_AUTH", "Not authorized to claim generator." },
{ tefBAD_LEDGER, "tefBAD_LEDGER", "Ledger in unexpected state." },
{ tefCLAIMED, "tefCLAIMED", "Can not claim a previously claimed account." },
{ tefEXCEPTION, "tefEXCEPTION", "Unexpected program state." },
{ tefCREATED, "tefCREATED", "Can't add an already created account." },
{ tefGEN_IN_USE, "tefGEN_IN_USE", "Generator already in use." },
{ tefPAST_SEQ, "tefPAST_SEQ", "This sequence number has already past" },
@@ -62,6 +63,8 @@ bool transResultInfo(TransactionEngineResult terCode, std::string& strToken, std
{ temBAD_EXPIRATION, "temBAD_EXPIRATION", "Malformed." },
{ temBAD_ISSUER, "temBAD_ISSUER", "Malformed." },
{ temBAD_OFFER, "temBAD_OFFER", "Malformed." },
{ temBAD_PATH, "temBAD_PATH", "Malformed." },
{ temBAD_PATH_LOOP, "temBAD_PATH_LOOP", "Malformed." },
{ temBAD_PUBLISH, "temBAD_PUBLISH", "Malformed: bad publish." },
{ temBAD_SET_ID, "temBAD_SET_ID", "Malformed." },
{ temCREATEXNS, "temCREATEXNS", "Can not specify non XNS for Create." },
@@ -82,6 +85,7 @@ bool transResultInfo(TransactionEngineResult terCode, std::string& strToken, std
{ terINSUF_FEE_B, "terINSUF_FEE_B", "Account balance can't pay fee." },
{ terNO_ACCOUNT, "terNO_ACCOUNT", "The source account does not exist." },
{ terNO_DST, "terNO_DST", "The destination does not exist" },
{ terNO_LINE, "terNO_LINE", "No such line." },
{ terNO_LINE_NO_ZERO, "terNO_LINE_NO_ZERO", "Can't zero non-existant line, destination might make it." },
{ terOFFER_NOT_FOUND, "terOFFER_NOT_FOUND", "Can not cancel offer." },
{ terPRE_SEQ, "terPRE_SEQ", "Missing/inapplicable prior transaction" },
@@ -431,10 +435,10 @@ STAmount TransactionEngine::accountSend(const uint160& uSenderID, const uint160&
return saActualCost;
}
TransactionEngineResult TransactionEngine::offerDelete(const SLE::pointer& sleOffer, const uint256& uOfferIndex, const uint160& uOwnerID)
TER TransactionEngine::offerDelete(const SLE::pointer& sleOffer, const uint256& uOfferIndex, const uint160& uOwnerID)
{
uint64 uOwnerNode = sleOffer->getIFieldU64(sfOwnerNode);
TransactionEngineResult terResult = dirDelete(false, uOwnerNode, Ledger::getOwnerDirIndex(uOwnerID), uOfferIndex, false);
uint64 uOwnerNode = sleOffer->getIFieldU64(sfOwnerNode);
TER terResult = dirDelete(false, uOwnerNode, Ledger::getOwnerDirIndex(uOwnerID), uOfferIndex, false);
if (tesSUCCESS == terResult)
{
@@ -449,7 +453,7 @@ TransactionEngineResult TransactionEngine::offerDelete(const SLE::pointer& sleOf
return terResult;
}
TransactionEngineResult TransactionEngine::offerDelete(const uint256& uOfferIndex)
TER TransactionEngine::offerDelete(const uint256& uOfferIndex)
{
SLE::pointer sleOffer = entryCache(ltOFFER, uOfferIndex);
const uint160 uOwnerID = sleOffer->getIValueFieldAccount(sfAccount).getAccountID();
@@ -462,7 +466,7 @@ TransactionEngineResult TransactionEngine::offerDelete(const uint256& uOfferInde
// --> uLedgerIndex: Value to add to directory.
// We only append. This allow for things that watch append only structure to just monitor from the last node on ward.
// Within a node with no deletions order of elements is sequential. Otherwise, order of elements is random.
TransactionEngineResult TransactionEngine::dirAdd(
TER TransactionEngine::dirAdd(
uint64& uNodeDir,
const uint256& uRootIndex,
const uint256& uLedgerIndex)
@@ -551,7 +555,7 @@ TransactionEngineResult TransactionEngine::dirAdd(
}
// Ledger must be in a state for this to work.
TransactionEngineResult TransactionEngine::dirDelete(
TER TransactionEngine::dirDelete(
const bool bKeepRoot, // --> True, if we never completely clean up, after we overflow the root node.
const uint64& uNodeDir, // --> Node containing entry.
const uint256& uRootIndex, // --> The index of the base of the directory. Nodes are based off of this.
@@ -779,7 +783,7 @@ bool TransactionEngine::dirNext(
}
// Set the authorized public key for an account. May also set the generator map.
TransactionEngineResult TransactionEngine::setAuthorized(const SerializedTransaction& txn, bool bMustSetGenerator)
TER TransactionEngine::setAuthorized(const SerializedTransaction& txn, bool bMustSetGenerator)
{
//
// Verify that submitter knows the private key for the generator.
@@ -919,7 +923,7 @@ void TransactionEngine::txnWrite()
}
}
TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTransaction& txn,
TER TransactionEngine::applyTransaction(const SerializedTransaction& txn,
TransactionEngineParams params)
{
Log(lsTRACE) << "applyTransaction>";
@@ -945,9 +949,8 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran
}
#endif
TransactionEngineResult terResult = tesSUCCESS;
uint256 txID = txn.getTransactionID();
TER terResult = tesSUCCESS;
uint256 txID = txn.getTransactionID();
if (!txID)
{
Log(lsWARNING) << "applyTransaction: invalid transaction id";
@@ -1330,7 +1333,7 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran
return terResult;
}
TransactionEngineResult TransactionEngine::doAccountSet(const SerializedTransaction& txn)
TER TransactionEngine::doAccountSet(const SerializedTransaction& txn)
{
Log(lsINFO) << "doAccountSet>";
@@ -1476,24 +1479,24 @@ TransactionEngineResult TransactionEngine::doAccountSet(const SerializedTransact
return tesSUCCESS;
}
TransactionEngineResult TransactionEngine::doClaim(const SerializedTransaction& txn)
TER TransactionEngine::doClaim(const SerializedTransaction& txn)
{
Log(lsINFO) << "doClaim>";
TransactionEngineResult terResult = setAuthorized(txn, true);
TER terResult = setAuthorized(txn, true);
Log(lsINFO) << "doClaim<";
return terResult;
}
TransactionEngineResult TransactionEngine::doCreditSet(const SerializedTransaction& txn)
TER TransactionEngine::doCreditSet(const SerializedTransaction& txn)
{
TransactionEngineResult terResult = tesSUCCESS;
TER terResult = tesSUCCESS;
Log(lsINFO) << "doCreditSet>";
// Check if destination makes sense.
uint160 uDstAccountID = txn.getITFieldAccount(sfDestination);
uint160 uDstAccountID = txn.getITFieldAccount(sfDestination);
if (!uDstAccountID)
{
@@ -1627,7 +1630,7 @@ TransactionEngineResult TransactionEngine::doCreditSet(const SerializedTransacti
return terResult;
}
TransactionEngineResult TransactionEngine::doNicknameSet(const SerializedTransaction& txn)
TER TransactionEngine::doNicknameSet(const SerializedTransaction& txn)
{
std::cerr << "doNicknameSet>" << std::endl;
@@ -1673,7 +1676,7 @@ TransactionEngineResult TransactionEngine::doNicknameSet(const SerializedTransac
return tesSUCCESS;
}
TransactionEngineResult TransactionEngine::doPasswordFund(const SerializedTransaction& txn)
TER TransactionEngine::doPasswordFund(const SerializedTransaction& txn)
{
std::cerr << "doPasswordFund>" << std::endl;
@@ -1707,7 +1710,7 @@ TransactionEngineResult TransactionEngine::doPasswordFund(const SerializedTransa
return tesSUCCESS;
}
TransactionEngineResult TransactionEngine::doPasswordSet(const SerializedTransaction& txn)
TER TransactionEngine::doPasswordSet(const SerializedTransaction& txn)
{
std::cerr << "doPasswordSet>" << std::endl;
@@ -1720,7 +1723,7 @@ TransactionEngineResult TransactionEngine::doPasswordSet(const SerializedTransac
mTxnAccount->setFlag(lsfPasswordSpent);
TransactionEngineResult terResult = setAuthorized(txn, false);
TER terResult = setAuthorized(txn, false);
std::cerr << "doPasswordSet<" << std::endl;
@@ -1740,9 +1743,9 @@ TransactionEngineResult TransactionEngine::doPasswordSet(const SerializedTransac
// <-- terResult : tesSUCCESS = no error and if !bAllowPartial complelely satisfied wanted.
// <-> usOffersDeleteAlways:
// <-> usOffersDeleteOnSuccess:
TransactionEngineResult calcOfferFill(paymentNode& pnSrc, paymentNode& pnDst, bool bAllowPartial)
TER calcOfferFill(paymentNode& pnSrc, paymentNode& pnDst, bool bAllowPartial)
{
TransactionEngineResult terResult;
TER terResult;
if (pnDst.saWanted.isNative())
{
@@ -1898,13 +1901,12 @@ void TransactionEngine::calcOfferBridgeNext(
}
#endif
// <-- bSuccess: false= no transfer
bool TransactionEngine::calcNodeOfferRev(
TER TransactionEngine::calcNodeOfferRev(
const unsigned int uIndex, // 0 < uIndex < uLast
const PathState::pointer& pspCur,
const bool bMultiQuality)
{
bool bSuccess = false;
TER terResult = tepPATH_DRY;
paymentNode& pnPrv = pspCur->vpnNodes[uIndex-1];
paymentNode& pnCur = pspCur->vpnNodes[uIndex];
@@ -1965,65 +1967,77 @@ bool TransactionEngine::calcNodeOfferRev(
SLE::pointer sleDirectDir = entryCache(ltDIR_NODE, uDirectTip);
const STAmount saOfrRate = STAmount::setRate(Ledger::getQuality(uDirectTip)); // For correct ratio
unsigned int uEntry = 0;
uint256 uCurIndex;
uint256 uOfferIndex;
while (saCurDlvReq != saCurDlvAct // Have not met request.
&& dirNext(uDirectTip, sleDirectDir, uEntry, uCurIndex))
&& dirNext(uDirectTip, sleDirectDir, uEntry, uOfferIndex))
{
Log(lsINFO) << boost::str(boost::format("calcNodeOfferRev: uCurIndex=%s") % uCurIndex.ToString());
Log(lsINFO) << boost::str(boost::format("calcNodeOfferRev: uOfferIndex=%s") % uOfferIndex.ToString());
SLE::pointer sleCurOfr = entryCache(ltOFFER, uCurIndex);
SLE::pointer sleOffer = entryCache(ltOFFER, uOfferIndex);
if (sleCurOfr->getIFieldPresent(sfExpiration) && sleCurOfr->getIFieldU32(sfExpiration) <= mLedger->getParentCloseTimeNC())
if (sleOffer->getIFieldPresent(sfExpiration) && sleOffer->getIFieldU32(sfExpiration) <= mLedger->getParentCloseTimeNC())
{
// Offer is expired.
Log(lsINFO) << "calcNodeOfferRev: encountered expired offer";
musUnfundedFound.insert(uCurIndex); // Mark offer for always deletion.
musUnfundedFound.insert(uOfferIndex); // Mark offer for always deletion.
continue;
}
const uint160 uCurOfrAccountID = sleCurOfr->getIValueFieldAccount(sfAccount).getAccountID();
const aciSource asLine = boost::make_tuple(uCurOfrAccountID, uCurCurrencyID, uCurIssuerID);
const uint160 uCurOfrAccountID = sleOffer->getIValueFieldAccount(sfAccount).getAccountID();
const aciSource asLine = boost::make_tuple(uCurOfrAccountID, uCurCurrencyID, uCurIssuerID);
// Allowed to access source from this node?
curIssuerNodeConstIterator it = pspCur->umReverse.find(asLine);
curIssuerNodeConstIterator itAllow = pspCur->umForward.find(asLine);
bool bFoundForward = itAllow != pspCur->umForward.end();
if (it == pspCur->umReverse.end())
if (bFoundForward || itAllow->second != uIndex)
{
// Temporarily unfunded. ignore in this column.
// Temporarily unfunded. Another node uses this source, ignore in this node.
nothing();
continue;
}
const STAmount& saCurOfrOutReq = sleCurOfr->getIValueFieldAmount(sfTakerGets);
// UNUSED? const STAmount& saCurOfrIn = sleCurOfr->getIValueFieldAmount(sfTakerPays);
const STAmount& saCurOfrOutReq = sleOffer->getIValueFieldAmount(sfTakerGets);
// UNUSED? const STAmount& saCurOfrIn = sleOffer->getIValueFieldAmount(sfTakerPays);
STAmount saCurOfrFunds = accountFunds(uCurOfrAccountID, saCurOfrOutReq); // Funds left.
STAmount saCurOfrFunds = accountFunds(uCurOfrAccountID, saCurOfrOutReq); // Funds left.
curIssuerNodeConstIterator itSourcePast = mumSource.find(asLine);
bool bFoundPast = itSourcePast != mumSource.end();
if (!saCurOfrFunds)
{
// Offer is unfunded.
Log(lsINFO) << "calcNodeOfferRev: encountered unfunded offer";
curIssuerNodeConstIterator itSource = mumSource.find(asLine);
if (itSource == mumSource.end())
curIssuerNodeConstIterator itSourceCur = bFoundPast
? pspCur->umReverse.end()
: pspCur->umReverse.find(asLine);
bool bFoundReverse = itSourceCur != pspCur->umReverse.end();
if (!bFoundReverse && !bFoundPast)
{
// Never mentioned before: found unfunded.
musUnfundedFound.insert(uCurIndex); // Mark offer for always deletion.
musUnfundedFound.insert(uOfferIndex); // Mark offer for always deletion.
}
else
{
// Mentioned before: source became unfunded.
pspCur->vUnfundedBecame.push_back(uCurIndex); // Mark offer for deletion on use.
pspCur->vUnfundedBecame.push_back(uOfferIndex); // Mark offer for deletion on use of current path state.
}
continue;
}
bool bMentioned = false;
if (!!uNxtAccountID)
{
// Next is an account.
// Next is redeeming it's own IOUs - no quality.
// Offer is paying out IOUs via offer - no quality.
STAmount saFeeRate = uCurOfrAccountID == uCurIssuerID || uNxtAccountID == uCurIssuerID
? saOne
@@ -2043,6 +2057,9 @@ bool TransactionEngine::calcNodeOfferRev(
saCurDlvAct += saOutDlvAct; // Portion of driver served.
saPrvDlvAct += saInDlvAct; // Portion needed in previous.
if (!bMentioned)
bMentioned = true;
}
else
{
@@ -2068,6 +2085,9 @@ bool TransactionEngine::calcNodeOfferRev(
{
// Do a directory.
// - Drive on computing saCurDlvAct to derive saPrvDlvAct.
// Although the fee varies based upon the next offer it does not matter as the offer maker knows in
// advance that they are obligated to pay a transfer fee of necessary. The owner of next offer has no
// expectation of a quality in being applied.
SLE::pointer sleNxtDir = entryCache(ltDIR_NODE, uNxtTip);
// ??? STAmount saOfrRate = STAmount::setRate(STAmount::getQuality(uNxtTip), uCurCurrencyID); // For correct ratio
unsigned int uEntry = 0;
@@ -2081,6 +2101,24 @@ bool TransactionEngine::calcNodeOfferRev(
uint160 uNxtOfrAccountID = sleNxtOfr->getIValueFieldAccount(sfAccount).getAccountID();
const STAmount& saNxtOfrIn = sleNxtOfr->getIValueFieldAmount(sfTakerPays);
const aciSource asLineNxt = boost::make_tuple(uNxtOfrAccountID, uNxtCurrencyID, uNxtIssuerID);
// Allowed to access source from this node?
curIssuerNodeConstIterator itAllowNxt = pspCur->umForward.find(asLineNxt);
curIssuerNodeConstIterator itNxt = itAllowNxt == pspCur->umForward.end()
? mumSource.find(asLine)
: itAllowNxt;
assert(itNxt != mumSource.end());
if (uIndex+1 != itNxt->second)
{
// Temporarily unfunded. Another node uses this source, ignore in this node.
nothing();
continue;
}
STAmount saFeeRate = uCurOfrAccountID == uCurIssuerID || uNxtOfrAccountID == uCurIssuerID
? saOne
: saTransferRate;
@@ -2101,6 +2139,8 @@ bool TransactionEngine::calcNodeOfferRev(
saCurDlvAct += saOutDlvAct; // Portion of driver served.
saPrvDlvAct += saInDlvAct; // Portion needed in previous.
if (!bMentioned)
bMentioned = true;
}
}
@@ -2109,6 +2149,14 @@ bool TransactionEngine::calcNodeOfferRev(
uNxtTip = 0;
}
}
if (bMentioned // Need to remember reverse mention.
&& !bFoundPast // Not mentioned in previous passes.
&& !bFoundForward) // Not mentioned for pass.
{
// Consider source mentioned by current path state.
pspCur->umReverse.insert(std::make_pair(asLine, uIndex));
}
}
}
@@ -2120,24 +2168,24 @@ bool TransactionEngine::calcNodeOfferRev(
if (saPrvDlvAct)
{
saPrvDlvReq = saPrvDlvAct; // Adjust request.
bSuccess = true;
terResult = tesSUCCESS;
}
Log(lsINFO) << boost::str(boost::format("calcNodeOfferRev< uIndex=%d saPrvDlvReq=%s bSuccess=%d")
Log(lsINFO) << boost::str(boost::format("calcNodeOfferRev< uIndex=%d saPrvDlvReq=%s terResult=%d")
% uIndex
% saPrvDlvReq.getFullText()
% bSuccess);
% terResult);
return bSuccess;
return terResult;
}
bool TransactionEngine::calcNodeOfferFwd(
TER TransactionEngine::calcNodeOfferFwd(
const unsigned int uIndex, // 0 < uIndex < uLast
const PathState::pointer& pspCur,
const bool bMultiQuality
)
{
bool bSuccess = false;
TER terResult = tepPATH_DRY;
paymentNode& pnPrv = pspCur->vpnNodes[uIndex-1];
paymentNode& pnCur = pspCur->vpnNodes[uIndex];
@@ -2331,10 +2379,10 @@ bool TransactionEngine::calcNodeOfferFwd(
if (saCurDlvAct)
{
saCurDlvReq = saCurDlvAct; // Adjust request.
bSuccess = true;
terResult = tesSUCCESS;
}
return bSuccess;
return terResult;
}
#if 0
@@ -2371,7 +2419,7 @@ void TransactionEngine::calcNodeOffer(
STAmount& saGot
) const
{
TransactionEngineResult terResult = temUNKNOWN;
TER terResult = temUNKNOWN;
// Direct: not bridging via XNS
bool bDirectNext = true; // True, if need to load.
@@ -2653,9 +2701,10 @@ Log(lsINFO) << boost::str(boost::format("calcNodeRipple:4: saCurReq=%s") % saCur
}
// Calculate saPrvRedeemReq, saPrvIssueReq, saPrvDeliver;
bool TransactionEngine::calcNodeAccountRev(const unsigned int uIndex, const PathState::pointer& pspCur, const bool bMultiQuality)
// <-- tesSUCCESS or tepPATH_DRY
TER TransactionEngine::calcNodeAccountRev(const unsigned int uIndex, const PathState::pointer& pspCur, const bool bMultiQuality)
{
bool bSuccess = true;
TER terResult = tesSUCCESS;
const unsigned int uLast = pspCur->vpnNodes.size() - 1;
paymentNode& pnPrv = pspCur->vpnNodes[uIndex ? uIndex-1 : 0];
@@ -2773,8 +2822,7 @@ bool TransactionEngine::calcNodeAccountRev(const unsigned int uIndex, const Path
if (!saCurWantedAct)
{
// Must have processed something.
// terResult = temBAD_AMOUNT;
bSuccess = false;
terResult = tepPATH_DRY;
}
}
else
@@ -2834,8 +2882,7 @@ bool TransactionEngine::calcNodeAccountRev(const unsigned int uIndex, const Path
if (!saCurRedeemAct && !saCurIssueAct)
{
// Must want something.
// terResult = temBAD_AMOUNT;
bSuccess = false;
terResult = tepPATH_DRY;
}
Log(lsINFO) << boost::str(boost::format("calcNodeAccountRev: ^|account --> ACCOUNT --> account : bPrvRedeem=%d bPrvIssue=%d bRedeem=%d bIssue=%d saCurRedeemReq=%s saCurIssueReq=%s saPrvOwed=%s saCurRedeemAct=%s saCurIssueAct=%s")
@@ -2880,8 +2927,7 @@ bool TransactionEngine::calcNodeAccountRev(const unsigned int uIndex, const Path
if (!saCurDeliverAct)
{
// Must want something.
// terResult = temBAD_AMOUNT;
bSuccess = false;
terResult = tepPATH_DRY;
}
Log(lsINFO) << boost::str(boost::format("calcNodeAccountRev: bPrvRedeem=%d bPrvIssue=%d bRedeem=%d bIssue=%d saCurDeliverReq=%s saCurDeliverAct=%s saPrvOwed=%s")
@@ -2912,8 +2958,7 @@ bool TransactionEngine::calcNodeAccountRev(const unsigned int uIndex, const Path
if (!saCurWantedAct)
{
// Must have processed something.
// terResult = temBAD_AMOUNT;
bSuccess = false;
terResult = tepPATH_DRY;
}
}
else
@@ -2950,8 +2995,7 @@ bool TransactionEngine::calcNodeAccountRev(const unsigned int uIndex, const Path
if (!saPrvDeliverAct)
{
// Must want something.
// terResult = temBAD_AMOUNT;
bSuccess = false;
terResult = tepPATH_DRY;
}
}
}
@@ -2971,13 +3015,11 @@ bool TransactionEngine::calcNodeAccountRev(const unsigned int uIndex, const Path
if (!saCurDeliverAct)
{
// Must want something.
// terResult = temBAD_AMOUNT;
bSuccess = false;
terResult = tepPATH_DRY;
}
}
// XXX Need a more nuanced return: temporary fail vs perm?
return bSuccess;
return terResult;
}
// The previous node: specifies what to push through to current.
@@ -2985,12 +3027,12 @@ bool TransactionEngine::calcNodeAccountRev(const unsigned int uIndex, const Path
// The current node: specify what to push through to next.
// - Output to next node minus fees.
// Perform balance adjustment with previous.
bool TransactionEngine::calcNodeAccountFwd(
TER TransactionEngine::calcNodeAccountFwd(
const unsigned int uIndex, // 0 <= uIndex <= uLast
const PathState::pointer& pspCur,
const bool bMultiQuality)
{
bool bSuccess = true;
TER terResult = tesSUCCESS;
const unsigned int uLast = pspCur->vpnNodes.size() - 1;
paymentNode& pnPrv = pspCur->vpnNodes[uIndex ? uIndex-1 : 0];
@@ -3251,7 +3293,7 @@ bool TransactionEngine::calcNodeAccountFwd(
// No income balance adjustments necessary. The paying side inside the offer paid and the next link will receive.
}
return bSuccess;
return terResult;
}
// Return true, iff lhs has less priority than rhs.
@@ -3275,10 +3317,10 @@ bool PathState::lessPriority(const PathState::pointer& lhs, const PathState::poi
// - A node names it's output.
// - A ripple nodes output issuer must be the node's account or the next node's account.
// - Offers can only go directly to another offer if the currency and issuer are an exact match.
bool PathState::pushImply(uint160 uAccountID, uint160 uCurrencyID, uint160 uIssuerID)
TER PathState::pushImply(uint160 uAccountID, uint160 uCurrencyID, uint160 uIssuerID)
{
const paymentNode& pnPrv = vpnNodes.back();
bool bValid = true;
const paymentNode& pnPrv = vpnNodes.back();
TER terResult = tesSUCCESS;
Log(lsINFO) << "pushImply> "
<< NewcoinAddress::createHumanAccountID(uAccountID)
@@ -3289,7 +3331,7 @@ bool PathState::pushImply(uint160 uAccountID, uint160 uCurrencyID, uint160 uIssu
{
// Need to convert via an offer.
bValid = pushNode(
terResult = pushNode(
STPathElement::typeCurrency // Offer.
| STPathElement::typeIssuer,
ACCOUNT_ONE, // Placeholder for offers.
@@ -3298,14 +3340,14 @@ bool PathState::pushImply(uint160 uAccountID, uint160 uCurrencyID, uint160 uIssu
}
if (bValid
if (tesSUCCESS == terResult
&& !!uCurrencyID // Not stamps.
&& (pnPrv.uAccountID != uIssuerID // Previous is not issuing own IOUs.
&& uAccountID != uIssuerID)) // Current is not receiving own IOUs.
{
// Need to ripple through uIssuerID's account.
bValid = pushNode(
terResult = pushNode(
STPathElement::typeAccount
| STPathElement::typeRedeem
| STPathElement::typeIssue,
@@ -3314,15 +3356,14 @@ bool PathState::pushImply(uint160 uAccountID, uint160 uCurrencyID, uint160 uIssu
uIssuerID);
}
Log(lsINFO) << "pushImply< " << bValid;
Log(lsINFO) << "pushImply< " << terResult;
return bValid;
return terResult;
}
// Append a node and insert before it any implied nodes.
// <-- bValid: true, if node is valid. false, if node is malformed or missing credit link.
// XXX Report missinge credit link distinct from malformed for retry.
bool PathState::pushNode(int iType, uint160 uAccountID, uint160 uCurrencyID, uint160 uIssuerID)
// <-- terResult: tesSUCCESS, temBAD_PATH, terNO_LINE
TER PathState::pushNode(int iType, uint160 uAccountID, uint160 uCurrencyID, uint160 uIssuerID)
{
Log(lsINFO) << "pushNode> "
<< NewcoinAddress::createHumanAccountID(uAccountID)
@@ -3341,7 +3382,7 @@ bool PathState::pushNode(int iType, uint160 uAccountID, uint160 uCurrencyID, uin
// true, iff account is allowed to redeem it's IOUs to next node.
const bool bRedeem = !!(iType & STPathElement::typeRedeem);
const bool bIssue = !!(iType & STPathElement::typeIssue);
bool bValid = true;
TER terResult = tesSUCCESS;
pnCur.uFlags = iType;
@@ -3349,7 +3390,7 @@ bool PathState::pushNode(int iType, uint160 uAccountID, uint160 uCurrencyID, uin
{
Log(lsINFO) << "pushNode: bad bits.";
bValid = false;
terResult = temBAD_PATH;
}
else if (bAccount)
{
@@ -3366,13 +3407,13 @@ bool PathState::pushNode(int iType, uint160 uAccountID, uint160 uCurrencyID, uin
if (!bFirst)
{
// Add required intermediate nodes to deliver to current account.
bValid = pushImply(
terResult = pushImply(
pnCur.uAccountID, // Current account.
pnCur.uCurrencyID, // Wanted currency.
!!pnCur.uCurrencyID ? uAccountID : ACCOUNT_XNS); // Account as issuer.
}
if (bValid && !vpnNodes.empty())
if (tesSUCCESS == terResult && !vpnNodes.empty())
{
const paymentNode& pnBck = vpnNodes.back();
bool bBckAccount = !!(pnBck.uFlags & STPathElement::typeAccount);
@@ -3391,7 +3432,7 @@ bool PathState::pushNode(int iType, uint160 uAccountID, uint160 uCurrencyID, uin
<< STAmount::createHumanCurrency(pnPrv.uCurrencyID)
<< "." ;
bValid = false;
terResult = terNO_LINE;
}
else
{
@@ -3406,14 +3447,14 @@ bool PathState::pushNode(int iType, uint160 uAccountID, uint160 uCurrencyID, uin
}
}
if (bValid)
if (tesSUCCESS == terResult)
vpnNodes.push_back(pnCur);
}
else
{
Log(lsINFO) << "pushNode: Account must redeem and/or issue.";
bValid = false;
terResult = temBAD_PATH;
}
}
else
@@ -3421,7 +3462,7 @@ bool PathState::pushNode(int iType, uint160 uAccountID, uint160 uCurrencyID, uin
// Offer link
if (bRedeem || bIssue)
{
bValid = false;
terResult = temBAD_PATH;
}
else
{
@@ -3434,7 +3475,7 @@ bool PathState::pushNode(int iType, uint160 uAccountID, uint160 uCurrencyID, uin
// Previous is an account.
// Insert intermediary account if needed.
bValid = pushImply(
terResult = pushImply(
!!pnPrv.uCurrencyID ? ACCOUNT_ONE : ACCOUNT_XNS,
pnPrv.uCurrencyID,
pnPrv.uIssuerID);
@@ -3446,7 +3487,7 @@ bool PathState::pushNode(int iType, uint160 uAccountID, uint160 uCurrencyID, uin
nothing();
}
if (bValid)
if (tesSUCCESS == terResult)
{
// Verify that previous account is allowed to issue.
const paymentNode& pnBck = vpnNodes.back();
@@ -3457,17 +3498,17 @@ bool PathState::pushNode(int iType, uint160 uAccountID, uint160 uCurrencyID, uin
{
Log(lsINFO) << "pushNode: previous account must be allowed to issue.";
bValid = false; // Malformed path.
terResult = temBAD_PATH;
}
}
if (bValid)
if (tesSUCCESS == terResult)
vpnNodes.push_back(pnCur);
}
}
Log(lsINFO) << "pushNode< " << bValid;
Log(lsINFO) << "pushNode< " << terResult;
return bValid;
return terResult;
}
PathState::PathState(
@@ -3494,7 +3535,7 @@ PathState::PathState(
saOutReq = saSend;
// Push sending node.
bValid = pushNode(
terStatus = pushNode(
STPathElement::typeAccount
| STPathElement::typeRedeem
| STPathElement::typeIssue
@@ -3506,18 +3547,18 @@ PathState::PathState(
BOOST_FOREACH(const STPathElement& speElement, spSourcePath)
{
if (bValid)
bValid = pushNode(speElement.getNodeType(), speElement.getAccountID(), speElement.getCurrency(), speElement.getIssuerID());
if (tesSUCCESS == terStatus)
terStatus = pushNode(speElement.getNodeType(), speElement.getAccountID(), speElement.getCurrency(), speElement.getIssuerID());
}
if (bValid)
if (tesSUCCESS == terStatus)
{
// Create receiver node.
bValid = pushImply(uReceiverID, uOutCurrencyID, uOutIssuerID);
if (bValid)
terStatus = pushImply(uReceiverID, uOutCurrencyID, uOutIssuerID);
if (tesSUCCESS == terStatus)
{
bValid = pushNode(
terStatus = pushNode(
STPathElement::typeAccount // Last node is always an account.
| STPathElement::typeRedeem // Does not matter just pass error check.
| STPathElement::typeIssue // Does not matter just pass error check.
@@ -3529,14 +3570,14 @@ PathState::PathState(
}
}
if (bValid)
if (tesSUCCESS == terStatus)
{
// Look for first mention of source in nodes and detect loops.
// Note: The output is not allowed to be a source.
const unsigned int uNodes = vpnNodes.size();
for (unsigned int uIndex = 0; bValid && uIndex != uNodes; ++uIndex)
for (unsigned int uIndex = 0; tesSUCCESS == terStatus && uIndex != uNodes; ++uIndex)
{
const paymentNode& pnCur = vpnNodes[uIndex];
@@ -3551,7 +3592,7 @@ PathState::PathState(
Log(lsINFO) << boost::str(boost::format("PathState: loop detected: %s")
% getJson());
bValid = false;
terStatus = temBAD_PATH_LOOP;
}
}
}
@@ -3616,7 +3657,7 @@ Json::Value PathState::getJson() const
jvNodes.append(jvNode);
}
jvPathState["valid"] = bValid;
jvPathState["status"] = terStatus;
jvPathState["index"] = mIndex;
jvPathState["nodes"] = jvNodes;
@@ -3641,43 +3682,42 @@ Json::Value PathState::getJson() const
// Calculate a node and its previous nodes.
// From the destination work in reverse towards the source calculating how much must be asked for.
// Then work forward, figuring out how much can actually be delivered.
// --> bAllowPartial: If false, fail if can't meet requirements.
// <-- bValid: true=success, false=insufficient funds / liqudity.
// <-- terResult: tesSUCCESS or tepPATH_DRY
// <-> pnNodes:
// --> [end]saWanted.mAmount
// --> [all]saWanted.mCurrency
// --> [all]saAccount
// <-> [0]saWanted.mAmount : --> limit, <-- actual
bool TransactionEngine::calcNode(const unsigned int uIndex, const PathState::pointer& pspCur, const bool bMultiQuality)
TER TransactionEngine::calcNode(const unsigned int uIndex, const PathState::pointer& pspCur, const bool bMultiQuality)
{
const paymentNode& pnCur = pspCur->vpnNodes[uIndex];
const bool bCurAccount = !!(pnCur.uFlags & STPathElement::typeAccount);
bool bValid;
const paymentNode& pnCur = pspCur->vpnNodes[uIndex];
const bool bCurAccount = !!(pnCur.uFlags & STPathElement::typeAccount);
TER terResult;
Log(lsINFO) << boost::str(boost::format("calcNode> uIndex=%d") % uIndex);
// Do current node reverse.
bValid = bCurAccount
terResult = bCurAccount
? calcNodeAccountRev(uIndex, pspCur, bMultiQuality)
: calcNodeOfferRev(uIndex, pspCur, bMultiQuality);
// Do previous.
if (bValid && uIndex)
if (tesSUCCESS == terResult && uIndex)
{
bValid = calcNode(uIndex-1, pspCur, bMultiQuality);
terResult = calcNode(uIndex-1, pspCur, bMultiQuality);
}
// Do current node forward.
if (bValid)
if (tesSUCCESS == terResult)
{
bValid = bCurAccount
terResult = bCurAccount
? calcNodeAccountFwd(uIndex, pspCur, bMultiQuality)
: calcNodeOfferFwd(uIndex, pspCur, bMultiQuality);
}
Log(lsINFO) << boost::str(boost::format("calcNode< uIndex=%d bValid=%d") % uIndex % bValid);
Log(lsINFO) << boost::str(boost::format("calcNode< uIndex=%d terResult=%d") % uIndex % terResult);
return bValid;
return terResult;
}
// Calculate the next increment of a path.
@@ -3697,14 +3737,14 @@ void TransactionEngine::pathNext(const PathState::pointer& pspCur, const int iPa
pspCur->vUnfundedBecame.clear();
pspCur->umReverse.clear();
pspCur->bValid = calcNode(uLast, pspCur, iPaths == 1);
pspCur->terStatus = calcNode(uLast, pspCur, iPaths == 1);
Log(lsINFO) << "pathNext: bValid="
<< pspCur->bValid
Log(lsINFO) << "pathNext: terStatus="
<< pspCur->terStatus
<< " saOutAct=" << pspCur->saOutAct.getText()
<< " saInAct=" << pspCur->saInAct.getText();
pspCur->uQuality = pspCur->bValid
pspCur->uQuality = tesSUCCESS == pspCur->terStatus
? STAmount::getRate(pspCur->saOutAct, pspCur->saInAct) // Calculate relative quality.
: 0; // Mark path as inactive.
@@ -3712,7 +3752,7 @@ void TransactionEngine::pathNext(const PathState::pointer& pspCur, const int iPa
}
// XXX Need to audit for things like setting accountID not having memory.
TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction& txn)
TER TransactionEngine::doPayment(const SerializedTransaction& txn)
{
// Ripple if source or destination is non-native or if there are paths.
const uint32 uTxFlags = txn.getFlags();
@@ -3835,6 +3875,8 @@ TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction
// Incrementally search paths.
std::vector<PathState::pointer> vpsPaths;
TER terResult = temUNCERTAIN;
if (!bNoRippleDirect)
{
// Direct path.
@@ -3853,7 +3895,19 @@ TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction
bPartialPayment);
if (pspDirect)
{
// Return if malformed.
if (pspDirect->terStatus >= temMALFORMED && pspDirect->terStatus < tefFAILURE)
return pspDirect->terStatus;
if (tesSUCCESS == pspDirect->terStatus)
{
// Had a success.
terResult = tesSUCCESS;
}
vpsPaths.push_back(pspDirect);
}
}
Log(lsINFO) << "doPayment: Paths: " << spsPaths.getPathCount();
@@ -3874,15 +3928,40 @@ TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction
bPartialPayment);
if (pspExpanded)
{
// Return if malformed.
if (pspExpanded->terStatus >= temMALFORMED && pspExpanded->terStatus < tefFAILURE)
return pspExpanded->terStatus;
if (tesSUCCESS == pspExpanded->terStatus)
{
// Had a success.
terResult = tesSUCCESS;
}
vpsPaths.push_back(pspExpanded);
}
}
TransactionEngineResult terResult;
STAmount saPaid;
STAmount saWanted;
LedgerEntrySet lesBase = mNodes; // Checkpoint with just fees paid.
if (vpsPaths.empty())
{
return tefEXCEPTION;
}
else if (tesSUCCESS != terResult)
{
// No path successes.
return vpsPaths[0]->terStatus;
}
else
{
terResult = temUNCERTAIN;
}
STAmount saPaid;
STAmount saWanted;
LedgerEntrySet lesBase = mNodes; // Checkpoint with just fees paid.
terResult = temUNCERTAIN;
while (temUNCERTAIN == terResult)
{
PathState::pointer pspBest;
@@ -3977,7 +4056,7 @@ TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction
return terResult;
}
TransactionEngineResult TransactionEngine::doWalletAdd(const SerializedTransaction& txn)
TER TransactionEngine::doWalletAdd(const SerializedTransaction& txn)
{
std::cerr << "WalletAdd>" << std::endl;
@@ -4033,7 +4112,7 @@ TransactionEngineResult TransactionEngine::doWalletAdd(const SerializedTransacti
return tesSUCCESS;
}
TransactionEngineResult TransactionEngine::doInvoice(const SerializedTransaction& txn)
TER TransactionEngine::doInvoice(const SerializedTransaction& txn)
{
return temUNKNOWN;
}
@@ -4046,7 +4125,7 @@ TransactionEngineResult TransactionEngine::doInvoice(const SerializedTransaction
// <-- saTakerGot: What taker got not including fees. To reduce an offer.
// <-- terResult: tesSUCCESS or terNO_ACCOUNT
// XXX: Fees should be paid by the source of the currency.
TransactionEngineResult TransactionEngine::takeOffers(
TER TransactionEngine::takeOffers(
bool bPassive,
const uint256& uBookBase,
const uint160& uTakerAccountID,
@@ -4067,7 +4146,7 @@ TransactionEngineResult TransactionEngine::takeOffers(
const uint160 uTakerPaysCurrency = saTakerPays.getCurrency();
const uint160 uTakerGetsAccountID = saTakerGets.getIssuer();
const uint160 uTakerGetsCurrency = saTakerGets.getCurrency();
TransactionEngineResult terResult = temUNCERTAIN;
TER terResult = temUNCERTAIN;
boost::unordered_set<uint256> usOfferUnfundedFound; // Offers found unfunded.
boost::unordered_set<uint256> usOfferUnfundedBecame; // Offers that became unfunded.
@@ -4271,7 +4350,7 @@ TransactionEngineResult TransactionEngine::takeOffers(
return terResult;
}
TransactionEngineResult TransactionEngine::doOfferCreate(const SerializedTransaction& txn)
TER TransactionEngine::doOfferCreate(const SerializedTransaction& txn)
{
Log(lsWARNING) << "doOfferCreate> " << txn.getJson(0);
const uint32 txFlags = txn.getFlags();
@@ -4295,7 +4374,7 @@ Log(lsWARNING) << "doOfferCreate: saTakerGets=" << saTakerGets.getFullText();
const uint160 uGetsCurrency = saTakerGets.getCurrency();
const uint64 uRate = STAmount::getRate(saTakerGets, saTakerPays);
TransactionEngineResult terResult = tesSUCCESS;
TER terResult = tesSUCCESS;
uint256 uDirectory; // Delete hints.
uint64 uOwnerNode;
uint64 uBookNode;
@@ -4458,12 +4537,12 @@ Log(lsWARNING) << "doOfferCreate: saTakerGets=" << saTakerGets.getFullText();
return terResult;
}
TransactionEngineResult TransactionEngine::doOfferCancel(const SerializedTransaction& txn)
TER TransactionEngine::doOfferCancel(const SerializedTransaction& txn)
{
TransactionEngineResult terResult;
const uint32 uSequence = txn.getITFieldU32(sfOfferSequence);
const uint256 uOfferIndex = Ledger::getOfferIndex(mTxnAccountID, uSequence);
SLE::pointer sleOffer = entryCache(ltOFFER, uOfferIndex);
TER terResult;
const uint32 uSequence = txn.getITFieldU32(sfOfferSequence);
const uint256 uOfferIndex = Ledger::getOfferIndex(mTxnAccountID, uSequence);
SLE::pointer sleOffer = entryCache(ltOFFER, uOfferIndex);
if (sleOffer)
{
@@ -4484,17 +4563,17 @@ TransactionEngineResult TransactionEngine::doOfferCancel(const SerializedTransac
return terResult;
}
TransactionEngineResult TransactionEngine::doTake(const SerializedTransaction& txn)
TER TransactionEngine::doTake(const SerializedTransaction& txn)
{
return temUNKNOWN;
}
TransactionEngineResult TransactionEngine::doStore(const SerializedTransaction& txn)
TER TransactionEngine::doStore(const SerializedTransaction& txn)
{
return temUNKNOWN;
}
TransactionEngineResult TransactionEngine::doDelete(const SerializedTransaction& txn)
TER TransactionEngine::doDelete(const SerializedTransaction& txn)
{
return temUNKNOWN;
}

View File

@@ -2,6 +2,7 @@
#define __TRANSACTIONENGINE__
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_comparison.hpp>
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
@@ -13,7 +14,7 @@
// A TransactionEngine applies serialized transactions to a ledger
// It can also, verify signatures, verify fees, and give rejection reasons
enum TransactionEngineResult
enum TER // aka TransactionEngineResult
{
// Note: Range is stable. Exact numbers are currently unstable. Use tokens.
@@ -32,6 +33,8 @@ enum TransactionEngineResult
temBAD_EXPIRATION,
temBAD_ISSUER,
temBAD_OFFER,
temBAD_PATH,
temBAD_PATH_LOOP,
temBAD_PUBLISH,
temBAD_SET_ID,
temCREATEXNS,
@@ -56,6 +59,7 @@ enum TransactionEngineResult
tefBAD_LEDGER,
tefCLAIMED,
tefCREATED,
tefEXCEPTION,
tefGEN_IN_USE,
tefPAST_SEQ,
@@ -67,6 +71,7 @@ enum TransactionEngineResult
terINSUF_FEE_B,
terNO_ACCOUNT,
terNO_DST,
terNO_LINE,
terNO_LINE_NO_ZERO,
terOFFER_NOT_FOUND, // XXX If we check sequence first this could be hard failure.
terPRE_SEQ,
@@ -84,7 +89,7 @@ enum TransactionEngineResult
tepPATH_PARTIAL,
};
bool transResultInfo(TransactionEngineResult terCode, std::string& strToken, std::string& strHuman);
bool transResultInfo(TER terCode, std::string& strToken, std::string& strHuman);
enum TransactionEngineParams
{
@@ -122,6 +127,7 @@ typedef boost::unordered_map<aciSource, unsigned int> curIssuerNode; // Map
typedef boost::unordered_map<aciSource, unsigned int>::const_iterator curIssuerNodeConstIterator;
extern std::size_t hash_value(const aciSource& asValue);
// extern std::size_t hash_value(const boost::tuple<uint160, uint160, uint160>& bt);
// Hold a path state under incremental application.
class PathState
@@ -129,26 +135,26 @@ class PathState
protected:
Ledger::pointer mLedger;
bool pushNode(int iType, uint160 uAccountID, uint160 uCurrencyID, uint160 uIssuerID);
bool pushImply(uint160 uAccountID, uint160 uCurrencyID, uint160 uIssuerID);
TER pushNode(int iType, uint160 uAccountID, uint160 uCurrencyID, uint160 uIssuerID);
TER pushImply(uint160 uAccountID, uint160 uCurrencyID, uint160 uIssuerID);
public:
typedef boost::shared_ptr<PathState> pointer;
bool bValid;
std::vector<paymentNode> vpnNodes;
TER terStatus;
std::vector<paymentNode> vpnNodes;
// When processing, don't want to complicate directory walking with deletion.
std::vector<uint256> vUnfundedBecame; // Offers that became unfunded.
std::vector<uint256> vUnfundedBecame; // Offers that became unfunded.
// First time working foward a funding source was mentioned for accounts. Source may only be used there.
curIssuerNode umForward; // Map of currency, issuer to node index.
curIssuerNode umForward; // Map of currency, issuer to node index.
// First time working in reverse a funding source was used.
// Source may only be used there if not mentioned by an account.
curIssuerNode umReverse; // Map of currency, issuer to node index.
curIssuerNode umReverse; // Map of currency, issuer to node index.
LedgerEntrySet lesEntries;
LedgerEntrySet lesEntries;
int mIndex;
uint64 uQuality; // 0 = none.
@@ -183,9 +189,7 @@ public:
const bool bPartialPayment
)
{
PathState::pointer pspNew = boost::make_shared<PathState>(lpLedger, iIndex, lesSource, spSourcePath, uReceiverID, uSenderID, saSend, saSendMax, bPartialPayment);
return pspNew && pspNew->bValid ? pspNew : PathState::pointer();
return boost::make_shared<PathState>(lpLedger, iIndex, lesSource, spSourcePath, uReceiverID, uSenderID, saSend, saSendMax, bPartialPayment);
}
static bool lessPriority(const PathState::pointer& lhs, const PathState::pointer& rhs);
@@ -198,12 +202,12 @@ class TransactionEngine
private:
LedgerEntrySet mNodes;
TransactionEngineResult dirAdd(
TER dirAdd(
uint64& uNodeDir, // Node of entry.
const uint256& uRootIndex,
const uint256& uLedgerIndex);
TransactionEngineResult dirDelete(
TER dirDelete(
const bool bKeepRoot,
const uint64& uNodeDir, // Node item is mentioned in.
const uint256& uRootIndex,
@@ -213,9 +217,9 @@ private:
bool dirFirst(const uint256& uRootIndex, SLE::pointer& sleNode, unsigned int& uDirEntry, uint256& uEntryIndex);
bool dirNext(const uint256& uRootIndex, SLE::pointer& sleNode, unsigned int& uDirEntry, uint256& uEntryIndex);
TransactionEngineResult setAuthorized(const SerializedTransaction& txn, bool bMustSetGenerator);
TER setAuthorized(const SerializedTransaction& txn, bool bMustSetGenerator);
TransactionEngineResult takeOffers(
TER takeOffers(
bool bPassive,
const uint256& uBookBase,
const uint160& uTakerAccountID,
@@ -246,8 +250,8 @@ protected:
void entryDelete(SLE::pointer sleEntry, bool bUnfunded = false);
void entryModify(SLE::pointer sleEntry);
TransactionEngineResult offerDelete(const uint256& uOfferIndex);
TransactionEngineResult offerDelete(const SLE::pointer& sleOffer, const uint256& uOfferIndex, const uint160& uOwnerID);
TER offerDelete(const uint256& uOfferIndex);
TER offerDelete(const SLE::pointer& sleOffer, const uint256& uOfferIndex, const uint160& uOwnerID);
uint32 rippleTransferRate(const uint160& uIssuerID);
STAmount rippleOwed(const uint160& uToAccountID, const uint160& uFromAccountID, const uint160& uCurrencyID);
@@ -267,31 +271,31 @@ protected:
PathState::pointer pathCreate(const STPath& spPath);
void pathNext(const PathState::pointer& pspCur, const int iPaths);
bool calcNode(const unsigned int uIndex, const PathState::pointer& pspCur, const bool bMultiQuality);
bool calcNodeOfferRev(const unsigned int uIndex, const PathState::pointer& pspCur, const bool bMultiQuality);
bool calcNodeOfferFwd(const unsigned int uIndex, const PathState::pointer& pspCur, const bool bMultiQuality);
bool calcNodeAccountRev(const unsigned int uIndex, const PathState::pointer& pspCur, const bool bMultiQuality);
bool calcNodeAccountFwd(const unsigned int uIndex, const PathState::pointer& pspCur, const bool bMultiQuality);
TER calcNode(const unsigned int uIndex, const PathState::pointer& pspCur, const bool bMultiQuality);
TER calcNodeOfferRev(const unsigned int uIndex, const PathState::pointer& pspCur, const bool bMultiQuality);
TER calcNodeOfferFwd(const unsigned int uIndex, const PathState::pointer& pspCur, const bool bMultiQuality);
TER calcNodeAccountRev(const unsigned int uIndex, const PathState::pointer& pspCur, const bool bMultiQuality);
TER calcNodeAccountFwd(const unsigned int uIndex, const PathState::pointer& pspCur, const bool bMultiQuality);
void calcNodeRipple(const uint32 uQualityIn, const uint32 uQualityOut,
const STAmount& saPrvReq, const STAmount& saCurReq,
STAmount& saPrvAct, STAmount& saCurAct);
void txnWrite();
TransactionEngineResult doAccountSet(const SerializedTransaction& txn);
TransactionEngineResult doClaim(const SerializedTransaction& txn);
TransactionEngineResult doCreditSet(const SerializedTransaction& txn);
TransactionEngineResult doDelete(const SerializedTransaction& txn);
TransactionEngineResult doInvoice(const SerializedTransaction& txn);
TransactionEngineResult doOfferCreate(const SerializedTransaction& txn);
TransactionEngineResult doOfferCancel(const SerializedTransaction& txn);
TransactionEngineResult doNicknameSet(const SerializedTransaction& txn);
TransactionEngineResult doPasswordFund(const SerializedTransaction& txn);
TransactionEngineResult doPasswordSet(const SerializedTransaction& txn);
TransactionEngineResult doPayment(const SerializedTransaction& txn);
TransactionEngineResult doStore(const SerializedTransaction& txn);
TransactionEngineResult doTake(const SerializedTransaction& txn);
TransactionEngineResult doWalletAdd(const SerializedTransaction& txn);
TER doAccountSet(const SerializedTransaction& txn);
TER doClaim(const SerializedTransaction& txn);
TER doCreditSet(const SerializedTransaction& txn);
TER doDelete(const SerializedTransaction& txn);
TER doInvoice(const SerializedTransaction& txn);
TER doOfferCreate(const SerializedTransaction& txn);
TER doOfferCancel(const SerializedTransaction& txn);
TER doNicknameSet(const SerializedTransaction& txn);
TER doPasswordFund(const SerializedTransaction& txn);
TER doPasswordSet(const SerializedTransaction& txn);
TER doPayment(const SerializedTransaction& txn);
TER doStore(const SerializedTransaction& txn);
TER doTake(const SerializedTransaction& txn);
TER doWalletAdd(const SerializedTransaction& txn);
public:
TransactionEngine() { ; }
@@ -300,7 +304,7 @@ public:
Ledger::pointer getLedger() { return mLedger; }
void setLedger(const Ledger::pointer& ledger) { assert(ledger); mLedger = ledger; }
TransactionEngineResult applyTransaction(const SerializedTransaction&, TransactionEngineParams);
TER applyTransaction(const SerializedTransaction&, TransactionEngineParams);
};
inline TransactionEngineParams operator|(const TransactionEngineParams& l1, const TransactionEngineParams& l2)