diff --git a/src/LedgerConsensus.cpp b/src/LedgerConsensus.cpp index 52e4173c1c..ae3c7813b7 100644 --- a/src/LedgerConsensus.cpp +++ b/src/LedgerConsensus.cpp @@ -799,7 +799,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"; @@ -861,7 +861,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; diff --git a/src/LedgerMaster.cpp b/src/LedgerMaster.cpp index e7b571f361..7228ff6b96 100644 --- a/src/LedgerMaster.cpp +++ b/src/LedgerMaster.cpp @@ -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; } diff --git a/src/LedgerMaster.h b/src/LedgerMaster.h index dd51333283..f3e58d5ba6 100644 --- a/src/LedgerMaster.h +++ b/src/LedgerMaster.h @@ -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); diff --git a/src/NetworkOPs.cpp b/src/NetworkOPs.cpp index 40cd4cc856..b2cbb51ce1 100644 --- a/src/NetworkOPs.cpp +++ b/src/NetworkOPs.cpp @@ -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) @@ -875,7 +875,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) { @@ -909,7 +909,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; @@ -927,7 +927,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"); @@ -937,7 +937,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 usisNotify; @@ -972,7 +972,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 sl(mMonitorLock); diff --git a/src/NetworkOPs.h b/src/NetworkOPs.h index 91ac722a05..9b324edddc 100644 --- a/src/NetworkOPs.h +++ b/src/NetworkOPs.h @@ -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 diff --git a/src/TransactionEngine.cpp b/src/TransactionEngine.cpp index df8a0c7082..b8b32e6f60 100644 --- a/src/TransactionEngine.cpp +++ b/src/TransactionEngine.cpp @@ -35,12 +35,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." }, @@ -430,10 +430,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) { @@ -448,7 +448,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(); @@ -461,7 +461,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) @@ -550,7 +550,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. @@ -778,7 +778,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. @@ -918,7 +918,7 @@ void TransactionEngine::txnWrite() } } -TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTransaction& txn, +TER TransactionEngine::applyTransaction(const SerializedTransaction& txn, TransactionEngineParams params) { Log(lsTRACE) << "applyTransaction>"; @@ -944,9 +944,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"; @@ -1329,7 +1328,7 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran return terResult; } -TransactionEngineResult TransactionEngine::doAccountSet(const SerializedTransaction& txn) +TER TransactionEngine::doAccountSet(const SerializedTransaction& txn) { Log(lsINFO) << "doAccountSet>"; @@ -1475,24 +1474,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) { @@ -1626,7 +1625,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; @@ -1672,7 +1671,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; @@ -1706,7 +1705,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; @@ -1719,7 +1718,7 @@ TransactionEngineResult TransactionEngine::doPasswordSet(const SerializedTransac mTxnAccount->setFlag(lsfPasswordSpent); - TransactionEngineResult terResult = setAuthorized(txn, false); + TER terResult = setAuthorized(txn, false); std::cerr << "doPasswordSet<" << std::endl; @@ -1739,9 +1738,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()) { @@ -1897,13 +1896,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]; @@ -1964,65 +1962,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 @@ -2042,6 +2052,9 @@ bool TransactionEngine::calcNodeOfferRev( saCurDlvAct += saOutDlvAct; // Portion of driver served. saPrvDlvAct += saInDlvAct; // Portion needed in previous. + + if (!bMentioned) + bMentioned = true; } else { @@ -2067,6 +2080,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; @@ -2080,6 +2096,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; @@ -2100,6 +2134,8 @@ bool TransactionEngine::calcNodeOfferRev( saCurDlvAct += saOutDlvAct; // Portion of driver served. saPrvDlvAct += saInDlvAct; // Portion needed in previous. + if (!bMentioned) + bMentioned = true; } } @@ -2108,6 +2144,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)); + } } } @@ -2119,24 +2163,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]; @@ -2330,10 +2374,10 @@ bool TransactionEngine::calcNodeOfferFwd( if (saCurDlvAct) { saCurDlvReq = saCurDlvAct; // Adjust request. - bSuccess = true; + terResult = tesSUCCESS; } - return bSuccess; + return terResult; } #if 0 @@ -2370,7 +2414,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. @@ -2652,9 +2696,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]; @@ -2772,8 +2817,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 @@ -2833,8 +2877,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") @@ -2879,8 +2922,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") @@ -2911,8 +2953,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 @@ -2949,8 +2990,7 @@ bool TransactionEngine::calcNodeAccountRev(const unsigned int uIndex, const Path if (!saPrvDeliverAct) { // Must want something. - // terResult = temBAD_AMOUNT; - bSuccess = false; + terResult = tepPATH_DRY; } } } @@ -2970,13 +3010,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. @@ -2984,12 +3022,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]; @@ -3250,7 +3288,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. @@ -3640,43 +3678,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. @@ -3711,7 +3748,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(); @@ -3876,10 +3913,10 @@ TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction vpsPaths.push_back(pspExpanded); } - TransactionEngineResult terResult; - STAmount saPaid; - STAmount saWanted; - LedgerEntrySet lesBase = mNodes; // Checkpoint with just fees paid. + TER terResult; + STAmount saPaid; + STAmount saWanted; + LedgerEntrySet lesBase = mNodes; // Checkpoint with just fees paid. terResult = temUNCERTAIN; while (temUNCERTAIN == terResult) @@ -3976,7 +4013,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; @@ -4032,7 +4069,7 @@ TransactionEngineResult TransactionEngine::doWalletAdd(const SerializedTransacti return tesSUCCESS; } -TransactionEngineResult TransactionEngine::doInvoice(const SerializedTransaction& txn) +TER TransactionEngine::doInvoice(const SerializedTransaction& txn) { return temUNKNOWN; } @@ -4045,7 +4082,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, @@ -4066,7 +4103,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 usOfferUnfundedFound; // Offers found unfunded. boost::unordered_set usOfferUnfundedBecame; // Offers that became unfunded. @@ -4270,7 +4307,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(); @@ -4294,7 +4331,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; @@ -4457,12 +4494,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) { @@ -4483,17 +4520,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; } diff --git a/src/TransactionEngine.h b/src/TransactionEngine.h index 5a88c1775c..4ae85c94f5 100644 --- a/src/TransactionEngine.h +++ b/src/TransactionEngine.h @@ -2,6 +2,7 @@ #define __TRANSACTIONENGINE__ #include +#include #include #include @@ -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. @@ -84,7 +85,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 +123,7 @@ typedef boost::unordered_map curIssuerNode; // Map typedef boost::unordered_map::const_iterator curIssuerNodeConstIterator; extern std::size_t hash_value(const aciSource& asValue); +// extern std::size_t hash_value(const boost::tuple& bt); // Hold a path state under incremental application. class PathState @@ -198,12 +200,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 +215,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 +248,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 +269,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 +302,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)