diff --git a/src/ripple_app/tx/OfferCreateTransactor.cpp b/src/ripple_app/tx/OfferCreateTransactor.cpp index a62de18df..17491252d 100644 --- a/src/ripple_app/tx/OfferCreateTransactor.cpp +++ b/src/ripple_app/tx/OfferCreateTransactor.cpp @@ -433,12 +433,6 @@ TER OfferCreateTransactor::doApply () terResult = temBAD_EXPIRATION; } - else if (bHaveExpiration && mEngine->getLedger ()->getParentCloseTimeNC () >= uExpiration) - { - WriteLog (lsWARNING, OfferCreateTransactor) << "OfferCreate: Expired transaction: offer expired"; - - terResult = tesSUCCESS; // Only charged fee. - } else if (saTakerPays.isNative () && saTakerGets.isNative ()) { WriteLog (lsWARNING, OfferCreateTransactor) << "OfferCreate: Malformed offer: XRP for XRP"; @@ -483,7 +477,7 @@ TER OfferCreateTransactor::doApply () } // Cancel offer. - if (tesSUCCESS == terResult && bHaveCancel) + if ((tesSUCCESS == terResult) && bHaveCancel) { const uint256 uCancelIndex = Ledger::getOfferIndex (mTxnAccountID, uCancelSequence); SLE::pointer sleCancel = mEngine->entryCache (ltOFFER, uCancelIndex); @@ -504,7 +498,8 @@ TER OfferCreateTransactor::doApply () } // Make sure authorized to hold what taker will pay. - if (tesSUCCESS == terResult && !saTakerPays.isNative ()) + bool bExpired = (bHaveExpiration && mEngine->getLedger ()->getParentCloseTimeNC () >= uExpiration); + if (tesSUCCESS == terResult && !saTakerPays.isNative () && !bExpired) { SLE::pointer sleTakerPays = mEngine->entryCache (ltACCOUNT_ROOT, Ledger::getAccountRootIndex (uPaysIssuerID)); @@ -512,19 +507,22 @@ TER OfferCreateTransactor::doApply () { WriteLog (lsWARNING, OfferCreateTransactor) << "OfferCreate: delay: can't receive IOUs from non-existent issuer: " << RippleAddress::createHumanAccountID (uPaysIssuerID); - terResult = terNO_ACCOUNT; + terResult = isSetBit (mParams, tapRETRY) ? terNO_ACCOUNT : tecNO_ISSUER; } else if (isSetBit (sleTakerPays->getFieldU32 (sfFlags), lsfRequireAuth)) { SLE::pointer sleRippleState = mEngine->entryCache (ltRIPPLE_STATE, Ledger::getRippleStateIndex (mTxnAccountID, uPaysIssuerID, uPaysCurrency)); bool bHigh = mTxnAccountID > uPaysIssuerID; - if (!sleRippleState - || !isSetBit (sleRippleState->getFieldU32 (sfFlags), (bHigh ? lsfHighAuth : lsfLowAuth))) + if (!sleRippleState) { - WriteLog (lsWARNING, OfferCreateTransactor) << "OfferCreate: delay: can't receive IOUs from issuer without auth."; + terResult = isSetBit (mParams, tapRETRY) ? terNO_LINE : tecNO_LINE; + } + else if (!isSetBit (sleRippleState->getFieldU32 (sfFlags), (bHigh ? lsfHighAuth : lsfLowAuth))) + { + WriteLog (lsDEBUG, OfferCreateTransactor) << "OfferCreate: delay: can't receive IOUs from issuer without auth."; - terResult = terNO_AUTH; + terResult = isSetBit (mParams, tapRETRY) ? terNO_AUTH : tecNO_AUTH; } } } @@ -534,7 +532,7 @@ TER OfferCreateTransactor::doApply () bool bUnfunded = false; const bool bOpenLedger = isSetBit (mParams, tapOPEN_LEDGER); - if (tesSUCCESS == terResult) + if ((tesSUCCESS == terResult) && !bExpired) { const uint256 uTakeBookBase = Ledger::getBookBase (uGetsCurrency, uGetsIssuerID, uPaysCurrency, uPaysIssuerID); @@ -586,6 +584,11 @@ TER OfferCreateTransactor::doApply () // Fail as is. nothing (); } + else if (bExpired) + { + // nothing to do + nothing (); + } else if (saTakerPays.isNegative () || saTakerGets.isNegative ()) { // If ledger is not final, can vote no. diff --git a/src/ripple_data/protocol/TER.cpp b/src/ripple_data/protocol/TER.cpp index 232260afa..ef9c44468 100644 --- a/src/ripple_data/protocol/TER.cpp +++ b/src/ripple_data/protocol/TER.cpp @@ -45,6 +45,9 @@ bool transResultInfo (TER terCode, std::string& strToken, std::string& strHuman) { tecUNFUNDED_OFFER, "tecUNFUNDED_OFFER", "Insufficient balance to fund created offer." }, { tecUNFUNDED_PAYMENT, "tecUNFUNDED_PAYMENT", "Insufficient XRP balance to send." }, { tecOWNERS, "tecOWNERS", "Non-zero owner count." }, + { tecNO_ISSUER, "tecNO_ISSUER", "Issuer account does not exist." }, + { tecNO_AUTH, "tecNO_AUTH", "Not authorized to hold asset." }, + { tecNO_LINE, "tecNO_LINE", "No such line." }, { tefFAILURE, "tefFAILURE", "Failed to apply." }, { tefALREADY, "tefALREADY", "The exact transaction was already in this ledger." }, diff --git a/src/ripple_data/protocol/TER.h b/src/ripple_data/protocol/TER.h index 912a54982..b3fd9fb80 100644 --- a/src/ripple_data/protocol/TER.h +++ b/src/ripple_data/protocol/TER.h @@ -138,7 +138,7 @@ enum TER // aka TransactionEngineResult // - Forwarded tesSUCCESS = 0, - // 100 .. 129 C Claim fee only (ripple transaction with no good paths, pay to non-existent account, no path) + // 100 .. 159 C Claim fee only (ripple transaction with no good paths, pay to non-existent account, no path) // Causes: // - Success, but does not achieve optimal result. // - Invalid transaction or no effect, but claim fee to use the sequence number. @@ -166,6 +166,9 @@ enum TER // aka TransactionEngineResult tecMASTER_DISABLED = 130, tecNO_REGULAR_KEY = 131, tecOWNERS = 132, + tecNO_ISSUER = 133, + tecNO_AUTH = 134, + tecNO_LINE = 135, }; // VFALCO TODO change these to normal functions.