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))
return nodeData;
auto txn = app_.getMasterTransaction().fetch(nodeHash.as_uint256(), false);
auto txn = app_.getMasterTransaction().fetch_from_cache (nodeHash.as_uint256());
if (txn)
{

View File

@@ -20,6 +20,7 @@
#ifndef 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/SHAMapTreeNode.h>
@@ -39,7 +40,10 @@ public:
TransactionMaster& operator= (TransactionMaster const&) = delete;
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>
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>
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;
txn = Transaction::load (txnID, mApp);
txn = Transaction::load (txnID, mApp, ec);
if (!txn)
return txn;
@@ -68,7 +74,7 @@ TransactionMaster::fetch (std::shared_ptr<SHAMapItem> const& item,
bool checkDisk, std::uint32_t uCommitLedger)
{
std::shared_ptr<STTx const> txn;
auto iTx = fetch (item->key(), false);
auto iTx = fetch_from_cache (item->key());
if (!iTx)
{

View File

@@ -20,6 +20,7 @@
#ifndef 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/STTx.h>
#include <ripple/protocol/TER.h>
@@ -74,14 +75,6 @@ public:
Blob const& rawTxn,
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
TransStatus
sqlTransactionStatus(boost::optional<std::string> const& status);
@@ -156,7 +149,7 @@ public:
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:
uint256 mTransactionID;

View File

@@ -25,6 +25,7 @@
#include <ripple/app/main/Application.h>
#include <ripple/app/misc/HashRouter.h>
#include <ripple/basics/safe_cast.h>
#include <ripple/protocol/ErrorCodes.h>
#include <ripple/protocol/Feature.h>
#include <ripple/protocol/jss.h>
#include <boost/optional.hpp>
@@ -99,25 +100,7 @@ Transaction::pointer Transaction::transactionFromSQL (
return tr;
}
Transaction::pointer Transaction::transactionFromSQLValidated(
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)
Transaction::pointer Transaction::load(uint256 const& id, Application& app, error_code_i& ec)
{
std::string sql = "SELECT LedgerSeq,Status,RawTxn "
"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),
soci::into (sociRawTxnBlob, rti);
if (!db->got_data () || rti != soci::i_ok)
{
ec = rpcTXN_NOT_FOUND;
return {};
}
convert(sociRawTxnBlob, rawTxn);
}
return Transaction::transactionFromSQLValidated (
std::shared_ptr<Transaction> txn;
try
{
txn = Transaction::transactionFromSQL(
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

View File

@@ -132,7 +132,8 @@ enum error_code_i
rpcNOT_IMPL = 74,
rpcNOT_SUPPORTED = 75,
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."},
{rpcUNKNOWN_COMMAND, "unknownCmd", "Unknown method."},
{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

View File

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