From 4a2af70c2cd8afbdec92cba24ee771e849f8651a Mon Sep 17 00:00:00 2001 From: Vinnie Falco Date: Tue, 30 Jun 2015 11:10:57 -0700 Subject: [PATCH] Return tefEXCEPTION in TransactionEngine --- src/ripple/app/tx/impl/TransactionEngine.cpp | 322 ++++++++++--------- 1 file changed, 170 insertions(+), 152 deletions(-) diff --git a/src/ripple/app/tx/impl/TransactionEngine.cpp b/src/ripple/app/tx/impl/TransactionEngine.cpp index 19abf5e13f..7ae86e2951 100644 --- a/src/ripple/app/tx/impl/TransactionEngine.cpp +++ b/src/ripple/app/tx/impl/TransactionEngine.cpp @@ -36,186 +36,204 @@ TransactionEngine::applyTransaction ( STTx const& txn, ViewFlags flags) { - assert (mLedger); + TER terResult = tefINTERNAL; + bool didApply = false; - WriteLog (lsTRACE, TransactionEngine) << "applyTransaction>"; - - uint256 const& txID = txn.getTransactionID (); - - if (!txID) + try { - WriteLog (lsWARNING, TransactionEngine) << - "applyTransaction: invalid transaction id"; - return std::make_pair(temINVALID_FLAG, false); - } + assert (mLedger); - mNodes.emplace(mLedger.get(), flags, txID); + WriteLog (lsTRACE, TransactionEngine) << "applyTransaction>"; -#ifdef BEAST_DEBUG - if (1) - { - Serializer ser; - txn.add (ser); - SerialIter sit(ser.slice()); - STTx s2 (sit); + uint256 const& txID = txn.getTransactionID (); - if (!s2.isEquivalent (txn)) + if (!txID) { - WriteLog (lsFATAL, TransactionEngine) << - "Transaction serdes mismatch"; - WriteLog (lsINFO, TransactionEngine) << txn.getJson (0); - WriteLog (lsFATAL, TransactionEngine) << s2.getJson (0); - assert (false); + WriteLog (lsWARNING, TransactionEngine) << + "applyTransaction: invalid transaction id"; + return std::make_pair(temINVALID_FLAG, false); } - } -#endif - TER terResult = Transactor::transact (txn, flags, this); - - if (terResult == temUNKNOWN) - { - WriteLog (lsWARNING, TransactionEngine) << - "applyTransaction: Invalid transaction: unknown transaction type"; - return std::make_pair(temUNKNOWN, false); - } - - if (ShouldLog (lsDEBUG, TransactionEngine)) - { - std::string strToken; - std::string strHuman; - - transResultInfo (terResult, strToken, strHuman); - - WriteLog (lsDEBUG, TransactionEngine) << - "applyTransaction: terResult=" << strToken << - " : " << terResult << - " : " << strHuman; - } - - bool didApply = isTesSuccess (terResult); - - if (isTecClaim (terResult) && !(flags & tapRETRY)) - { - // only claim the transaction fee - WriteLog (lsDEBUG, TransactionEngine) << - "Reprocessing tx " << txID << " to only claim fee"; mNodes.emplace(mLedger.get(), flags, txID); - SLE::pointer txnAcct = view().peek( - keylet::account(txn.getAccountID(sfAccount))); - - if (!txnAcct) - terResult = terNO_ACCOUNT; - else + #ifdef BEAST_DEBUG + if (1) { - std::uint32_t t_seq = txn.getSequence (); - std::uint32_t a_seq = txnAcct->getFieldU32 (sfSequence); + Serializer ser; + txn.add (ser); + SerialIter sit(ser.slice()); + STTx s2 (sit); - if (a_seq < t_seq) - terResult = terPRE_SEQ; - else if (a_seq > t_seq) - terResult = tefPAST_SEQ; + if (!s2.isEquivalent (txn)) + { + WriteLog (lsFATAL, TransactionEngine) << + "Transaction serdes mismatch"; + WriteLog (lsINFO, TransactionEngine) << txn.getJson (0); + WriteLog (lsFATAL, TransactionEngine) << s2.getJson (0); + assert (false); + } + } + #endif + + terResult = Transactor::transact (txn, flags, this); + + if (terResult == temUNKNOWN) + { + WriteLog (lsWARNING, TransactionEngine) << + "applyTransaction: Invalid transaction: unknown transaction type"; + return std::make_pair(temUNKNOWN, false); + } + + if (ShouldLog (lsDEBUG, TransactionEngine)) + { + std::string strToken; + std::string strHuman; + + transResultInfo (terResult, strToken, strHuman); + + WriteLog (lsDEBUG, TransactionEngine) << + "applyTransaction: terResult=" << strToken << + " : " << terResult << + " : " << strHuman; + } + + didApply = isTesSuccess (terResult); + + if (isTecClaim (terResult) && !(flags & tapRETRY)) + { + // only claim the transaction fee + WriteLog (lsDEBUG, TransactionEngine) << + "Reprocessing tx " << txID << " to only claim fee"; + mNodes.emplace(mLedger.get(), flags, txID); + + SLE::pointer txnAcct = view().peek( + keylet::account(txn.getAccountID(sfAccount))); + + if (!txnAcct) + terResult = terNO_ACCOUNT; else { - STAmount fee = txn.getTransactionFee (); - STAmount balance = txnAcct->getFieldAmount (sfBalance); + std::uint32_t t_seq = txn.getSequence (); + std::uint32_t a_seq = txnAcct->getFieldU32 (sfSequence); - // We retry/reject the transaction if the account - // balance is zero or we're applying against an open - // ledger and the balance is less than the fee - if ((balance == zero) || - ((flags & tapOPEN_LEDGER) && (balance < fee))) - { - // Account has no funds or ledger is open - terResult = terINSUF_FEE_B; - } + if (a_seq < t_seq) + terResult = terPRE_SEQ; + else if (a_seq > t_seq) + terResult = tefPAST_SEQ; else { - if (fee > balance) - fee = balance; - txnAcct->setFieldAmount (sfBalance, balance - fee); - txnAcct->setFieldU32 (sfSequence, t_seq + 1); - view().update (txnAcct); - didApply = true; + STAmount fee = txn.getTransactionFee (); + STAmount balance = txnAcct->getFieldAmount (sfBalance); + + // We retry/reject the transaction if the account + // balance is zero or we're applying against an open + // ledger and the balance is less than the fee + if ((balance == zero) || + ((flags & tapOPEN_LEDGER) && (balance < fee))) + { + // Account has no funds or ledger is open + terResult = terINSUF_FEE_B; + } + else + { + if (fee > balance) + fee = balance; + txnAcct->setFieldAmount (sfBalance, balance - fee); + txnAcct->setFieldU32 (sfSequence, t_seq + 1); + view().update (txnAcct); + didApply = true; + } } } } - } - else if (!didApply) - { - WriteLog (lsDEBUG, TransactionEngine) << "Not applying transaction " << txID; - } - - if (didApply && !checkInvariants (terResult, txn, flags)) - { - WriteLog (lsFATAL, TransactionEngine) << - "Transaction violates invariants"; - WriteLog (lsFATAL, TransactionEngine) << - txn.getJson (0); - WriteLog (lsFATAL, TransactionEngine) << - transToken (terResult) << ": " << transHuman (terResult); - WriteLog (lsFATAL, TransactionEngine) << - mNodes->getJson (0); - didApply = false; - terResult = tefINTERNAL; - } - - if (didApply) - { - // Transaction succeeded fully or (retries are not allowed and the - // transaction could claim a fee) - Serializer m; - mNodes->calcRawMeta (m, terResult, mTxnSeq++); - - mNodes->apply(*mLedger); - - Serializer s; - txn.add (s); - - if (flags & tapOPEN_LEDGER) + else if (!didApply) { - if (! mLedger->txInsert(txID, - std::make_shared< - Serializer const>(std::move(s)), - nullptr)) + WriteLog (lsDEBUG, TransactionEngine) << "Not applying transaction " << txID; + } + + if (didApply && !checkInvariants (terResult, txn, flags)) + { + WriteLog (lsFATAL, TransactionEngine) << + "Transaction violates invariants"; + WriteLog (lsFATAL, TransactionEngine) << + txn.getJson (0); + WriteLog (lsFATAL, TransactionEngine) << + transToken (terResult) << ": " << transHuman (terResult); + WriteLog (lsFATAL, TransactionEngine) << + mNodes->getJson (0); + didApply = false; + terResult = tefINTERNAL; + } + + if (didApply) + { + // Transaction succeeded fully or (retries are not allowed and the + // transaction could claim a fee) + Serializer m; + mNodes->calcRawMeta (m, terResult, mTxnSeq++); + + mNodes->apply(*mLedger); + + Serializer s; + txn.add (s); + + if (flags & tapOPEN_LEDGER) { - WriteLog (lsFATAL, TransactionEngine) << - "Duplicate transaction applied"; - assert (false); - throw std::runtime_error ("Duplicate transaction applied"); + if (! mLedger->txInsert(txID, + std::make_shared< + Serializer const>(std::move(s)), + nullptr)) + { + WriteLog (lsFATAL, TransactionEngine) << + "Duplicate transaction applied"; + assert (false); + throw std::runtime_error ("Duplicate transaction applied"); + } + } + else + { + if (! mLedger->txInsert(txID, + std::make_shared(std::move(s)), + std::make_shared(std::move(m)))) + { + WriteLog (lsFATAL, TransactionEngine) << + "Duplicate transaction applied to closed ledger"; + assert (false); + throw std::runtime_error ("Duplicate transaction applied to closed ledger"); + } + + // Charge whatever fee they specified. We break the encapsulation of + // STAmount here and use "special knowledge" - namely that a native + // amount is stored fully in the mantissa: + auto const fee = txn.getTransactionFee (); + + // The transactor guarantees these will never trigger + if (!fee.native () || fee.negative ()) + throw std::runtime_error ("amount is negative!"); + + if (fee != zero) + mLedger->destroyCoins (fee.mantissa ()); } } - else + + mNodes = boost::none; + + if (!(flags & tapOPEN_LEDGER) && isTemMalformed (terResult)) { - if (! mLedger->txInsert(txID, - std::make_shared(std::move(s)), - std::make_shared(std::move(m)))) - { - WriteLog (lsFATAL, TransactionEngine) << - "Duplicate transaction applied to closed ledger"; - assert (false); - throw std::runtime_error ("Duplicate transaction applied to closed ledger"); - } - - // Charge whatever fee they specified. We break the encapsulation of - // STAmount here and use "special knowledge" - namely that a native - // amount is stored fully in the mantissa: - auto const fee = txn.getTransactionFee (); - - // The transactor guarantees these will never trigger - if (!fee.native () || fee.negative ()) - throw std::runtime_error ("amount is negative!"); - - if (fee != zero) - mLedger->destroyCoins (fee.mantissa ()); + // XXX Malformed or failed transaction in closed ledger must bow out. } } - - mNodes = boost::none; - - if (!(flags & tapOPEN_LEDGER) && isTemMalformed (terResult)) + catch(std::exception const& e) { - // XXX Malformed or failed transaction in closed ledger must bow out. + WriteLog (lsFATAL, TransactionEngine) << + "Caught exception: " << e.what(); + return { tefEXCEPTION, false }; + } + catch(...) + { + WriteLog (lsFATAL, TransactionEngine) << + "Caught unknown exception"; + return { tefEXCEPTION, false }; } return { terResult, didApply };