Skip validity check for tx command:

* historical tx retrieval no longer needs to pass current validity check;
* introduced additional RPC error code for database deserialization error.

This fixes issue #2597
This commit is contained in:
ShangyanLi
2019-11-01 08:58:02 -04:00
committed by Nik Bougalis
parent ade1afe1b0
commit 11cf27e006
8 changed files with 45 additions and 40 deletions

View File

@@ -81,7 +81,7 @@ ConsensusTransSetSF::getNode (SHAMapHash const& nodeHash) const
if (m_nodeCache.retrieve (nodeHash, nodeData)) if (m_nodeCache.retrieve (nodeHash, nodeData))
return nodeData; return nodeData;
auto txn = app_.getMasterTransaction().fetch(nodeHash.as_uint256(), false); auto txn = app_.getMasterTransaction().fetch_from_cache (nodeHash.as_uint256());
if (txn) if (txn)
{ {

View File

@@ -20,6 +20,7 @@
#ifndef RIPPLE_APP_LEDGER_TRANSACTIONMASTER_H_INCLUDED #ifndef RIPPLE_APP_LEDGER_TRANSACTIONMASTER_H_INCLUDED
#define RIPPLE_APP_LEDGER_TRANSACTIONMASTER_H_INCLUDED #define RIPPLE_APP_LEDGER_TRANSACTIONMASTER_H_INCLUDED
#include <ripple/protocol/ErrorCodes.h>
#include <ripple/shamap/SHAMapItem.h> #include <ripple/shamap/SHAMapItem.h>
#include <ripple/shamap/SHAMapTreeNode.h> #include <ripple/shamap/SHAMapTreeNode.h>
@@ -39,7 +40,10 @@ public:
TransactionMaster& operator= (TransactionMaster const&) = delete; TransactionMaster& operator= (TransactionMaster const&) = delete;
std::shared_ptr<Transaction> std::shared_ptr<Transaction>
fetch (uint256 const& , bool checkDisk); fetch_from_cache (uint256 const&);
std::shared_ptr<Transaction>
fetch (uint256 const& , error_code_i& ec);
std::shared_ptr<STTx const> std::shared_ptr<STTx const>
fetch (std::shared_ptr<SHAMapItem> const& item, fetch (std::shared_ptr<SHAMapItem> const& item,

View File

@@ -45,14 +45,20 @@ bool TransactionMaster::inLedger (uint256 const& hash, std::uint32_t ledger)
} }
std::shared_ptr<Transaction> std::shared_ptr<Transaction>
TransactionMaster::fetch (uint256 const& txnID, bool checkDisk) TransactionMaster::fetch_from_cache (uint256 const& txnID)
{ {
auto txn = mCache.fetch (txnID); return mCache.fetch (txnID);
}
if (!checkDisk || txn) std::shared_ptr<Transaction>
TransactionMaster::fetch (uint256 const& txnID, error_code_i& ec)
{
auto txn = fetch_from_cache (txnID);
if (txn)
return txn; return txn;
txn = Transaction::load (txnID, mApp); txn = Transaction::load (txnID, mApp, ec);
if (!txn) if (!txn)
return txn; return txn;
@@ -68,7 +74,7 @@ TransactionMaster::fetch (std::shared_ptr<SHAMapItem> const& item,
bool checkDisk, std::uint32_t uCommitLedger) bool checkDisk, std::uint32_t uCommitLedger)
{ {
std::shared_ptr<STTx const> txn; std::shared_ptr<STTx const> txn;
auto iTx = fetch (item->key(), false); auto iTx = fetch_from_cache (item->key());
if (!iTx) if (!iTx)
{ {

View File

@@ -20,6 +20,7 @@
#ifndef RIPPLE_APP_MISC_TRANSACTION_H_INCLUDED #ifndef RIPPLE_APP_MISC_TRANSACTION_H_INCLUDED
#define RIPPLE_APP_MISC_TRANSACTION_H_INCLUDED #define RIPPLE_APP_MISC_TRANSACTION_H_INCLUDED
#include <ripple/protocol/ErrorCodes.h>
#include <ripple/protocol/Protocol.h> #include <ripple/protocol/Protocol.h>
#include <ripple/protocol/STTx.h> #include <ripple/protocol/STTx.h>
#include <ripple/protocol/TER.h> #include <ripple/protocol/TER.h>
@@ -74,14 +75,6 @@ public:
Blob const& rawTxn, Blob const& rawTxn,
Application& app); Application& app);
static
Transaction::pointer
transactionFromSQLValidated (
boost::optional<std::uint64_t> const& ledgerSeq,
boost::optional<std::string> const& status,
Blob const& rawTxn,
Application& app);
static static
TransStatus TransStatus
sqlTransactionStatus(boost::optional<std::string> const& status); sqlTransactionStatus(boost::optional<std::string> const& status);
@@ -156,7 +149,7 @@ public:
Json::Value getJson (JsonOptions options, bool binary = false) const; Json::Value getJson (JsonOptions options, bool binary = false) const;
static Transaction::pointer load (uint256 const& id, Application& app); static Transaction::pointer load (uint256 const& id, Application& app, error_code_i& ec);
private: private:
uint256 mTransactionID; uint256 mTransactionID;

View File

@@ -25,6 +25,7 @@
#include <ripple/app/main/Application.h> #include <ripple/app/main/Application.h>
#include <ripple/app/misc/HashRouter.h> #include <ripple/app/misc/HashRouter.h>
#include <ripple/basics/safe_cast.h> #include <ripple/basics/safe_cast.h>
#include <ripple/protocol/ErrorCodes.h>
#include <ripple/protocol/Feature.h> #include <ripple/protocol/Feature.h>
#include <ripple/protocol/jss.h> #include <ripple/protocol/jss.h>
#include <boost/optional.hpp> #include <boost/optional.hpp>
@@ -99,25 +100,7 @@ Transaction::pointer Transaction::transactionFromSQL (
return tr; return tr;
} }
Transaction::pointer Transaction::transactionFromSQLValidated( Transaction::pointer Transaction::load(uint256 const& id, Application& app, error_code_i& ec)
boost::optional<std::uint64_t> const& ledgerSeq,
boost::optional<std::string> const& status,
Blob const& rawTxn,
Application& app)
{
auto ret = transactionFromSQL(ledgerSeq, status, rawTxn, app);
if (checkValidity(app.getHashRouter(),
*ret->getSTransaction(), app.
getLedgerMaster().getValidatedRules(),
app.config()).first !=
Validity::Valid)
return {};
return ret;
}
Transaction::pointer Transaction::load(uint256 const& id, Application& app)
{ {
std::string sql = "SELECT LedgerSeq,Status,RawTxn " std::string sql = "SELECT LedgerSeq,Status,RawTxn "
"FROM Transactions WHERE TransID='"; "FROM Transactions WHERE TransID='";
@@ -135,13 +118,29 @@ Transaction::pointer Transaction::load(uint256 const& id, Application& app)
*db << sql, soci::into (ledgerSeq), soci::into (status), *db << sql, soci::into (ledgerSeq), soci::into (status),
soci::into (sociRawTxnBlob, rti); soci::into (sociRawTxnBlob, rti);
if (!db->got_data () || rti != soci::i_ok) if (!db->got_data () || rti != soci::i_ok)
{
ec = rpcTXN_NOT_FOUND;
return {}; return {};
}
convert(sociRawTxnBlob, rawTxn); convert(sociRawTxnBlob, rawTxn);
} }
return Transaction::transactionFromSQLValidated ( std::shared_ptr<Transaction> txn;
try
{
txn = Transaction::transactionFromSQL(
ledgerSeq, status, rawTxn, app); ledgerSeq, status, rawTxn, app);
}
catch (std::exception& e)
{
JLOG(app.journal("Ledger").warn())
<< "Unable to deserialize transaction from raw SQL value. Error: "
<< e.what();
ec = rpcDB_DESERIALIZATION;
}
return txn;
} }
// options 1 to include the date of the transaction // options 1 to include the date of the transaction

View File

@@ -132,7 +132,8 @@ enum error_code_i
rpcNOT_IMPL = 74, rpcNOT_IMPL = 74,
rpcNOT_SUPPORTED = 75, rpcNOT_SUPPORTED = 75,
rpcBAD_KEY_TYPE = 76, rpcBAD_KEY_TYPE = 76,
rpcLAST = rpcBAD_KEY_TYPE // rpcLAST should always equal the last code. rpcDB_DESERIALIZATION = 77,
rpcLAST = rpcDB_DESERIALIZATION // rpcLAST should always equal the last code.
}; };
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------

View File

@@ -88,6 +88,7 @@ constexpr static ErrorInfo unorderedErrorInfos[]
{rpcTXN_NOT_FOUND, "txnNotFound", "Transaction not found."}, {rpcTXN_NOT_FOUND, "txnNotFound", "Transaction not found."},
{rpcUNKNOWN_COMMAND, "unknownCmd", "Unknown method."}, {rpcUNKNOWN_COMMAND, "unknownCmd", "Unknown method."},
{rpcSENDMAX_MALFORMED, "sendMaxMalformed", "SendMax amount malformed."}, {rpcSENDMAX_MALFORMED, "sendMaxMalformed", "SendMax amount malformed."},
{rpcDB_DESERIALIZATION, "dbDeserialization", "Database deserialization error."},
}; };
// C++ does not allow you to return an array from a function. You must // C++ does not allow you to return an array from a function. You must

View File

@@ -97,11 +97,12 @@ Json::Value doTx (RPC::Context& context)
if (!isHexTxID (txid)) if (!isHexTxID (txid))
return rpcError (rpcNOT_IMPL); return rpcError (rpcNOT_IMPL);
error_code_i ec = rpcSUCCESS;
auto txn = context.app.getMasterTransaction ().fetch ( auto txn = context.app.getMasterTransaction ().fetch (
from_hex_text<uint256>(txid), true); from_hex_text<uint256>(txid), ec);
if (!txn) if (!txn)
return rpcError (rpcTXN_NOT_FOUND); return rpcError (ec);
Json::Value ret = txn->getJson (JsonOptions::include_date, binary); Json::Value ret = txn->getJson (JsonOptions::include_date, binary);