diff --git a/src/cpp/ripple/TransactionEngine.cpp b/src/cpp/ripple/TransactionEngine.cpp index e4cadfb99..1d9b33cc7 100644 --- a/src/cpp/ripple/TransactionEngine.cpp +++ b/src/cpp/ripple/TransactionEngine.cpp @@ -110,13 +110,50 @@ TER TransactionEngine::applyTransaction(const SerializedTransaction& txn, Transa cLog(lsINFO) << "applyTransaction: terResult=" << strToken << " : " << terResult << " : " << strHuman; - if (isTepPartial(terResult) && isSetBit(params, tapRETRY)) - { - // Partial result and allowed to retry, reclassify as a retry. - terResult = terRETRY; + bool applyTransaction = false; + + if (terResult == tesSUCCESS) + applyTransaction = true; + else if (isTepPartial(terResult) && !isSetBit(params, tapRETRY)) + applyTransaction = true; + else if (isTecClaim(terResult) && !isSetBit(params, tapRETRY)) + { // only claim the transaction fee + mNodes.clear(); + + SLE::pointer txnAcct = entryCache(ltACCOUNT_ROOT, Ledger::getAccountRootIndex(txn.getSourceAccount())); + if (!txnAcct) + terResult = terNO_ACCOUNT; + else + { + uint32 t_seq = txn.getSequence(); + uint32 a_seq = txnAcct->getFieldU32(sfSequence); + + if (t_seq != a_seq) + { + if (a_seq < t_seq) + terResult = terPRE_SEQ; + else + terResult = tefPAST_SEQ; + } + else + { + STAmount fee = txn.getTransactionFee(); + STAmount balance = txnAcct->getFieldAmount(sfBalance); + + if (balance < fee) + terResult = terINSUF_FEE_B; + else + { + txnAcct->setFieldAmount(sfBalance, balance - fee); + txnAcct->setFieldU32(sfSequence, t_seq + 1); + applyTransaction = true; + entryModify(txnAcct); + } + } + } } - if ((tesSUCCESS == terResult) || isTepPartial(terResult)) + if (applyTransaction) { // Transaction succeeded fully or (retries are not allowed and the transaction succeeded partially). Serializer m;