mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-01 08:25:51 +00:00
Add the 'fail_hard' flag for submitting and signing transactions. If fail
hard is set, on a local error, the transaction should be guaranteed not to happen unless it is resubmitted.
This commit is contained in:
@@ -197,12 +197,12 @@ void NetworkOPs::submitTransaction (Job&, SerializedTransaction::pointer iTrans,
|
|||||||
|
|
||||||
// FIXME: Should submit to job queue
|
// FIXME: Should submit to job queue
|
||||||
theApp->getIOService ().post (boost::bind (&NetworkOPs::processTransaction, this,
|
theApp->getIOService ().post (boost::bind (&NetworkOPs::processTransaction, this,
|
||||||
boost::make_shared<Transaction> (trans, false), false, callback));
|
boost::make_shared<Transaction> (trans, false), false, false, callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sterilize transaction through serialization.
|
// Sterilize transaction through serialization.
|
||||||
// This is fully synchronous and deprecated
|
// This is fully synchronous and deprecated
|
||||||
Transaction::pointer NetworkOPs::submitTransactionSync (Transaction::ref tpTrans, bool bAdmin, bool bSubmit)
|
Transaction::pointer NetworkOPs::submitTransactionSync (Transaction::ref tpTrans, bool bAdmin, bool bFailHard, bool bSubmit)
|
||||||
{
|
{
|
||||||
Serializer s;
|
Serializer s;
|
||||||
tpTrans->getSTransaction ()->add (s);
|
tpTrans->getSTransaction ()->add (s);
|
||||||
@@ -217,7 +217,7 @@ Transaction::pointer NetworkOPs::submitTransactionSync (Transaction::ref tpTrans
|
|||||||
else if (tpTransNew->getSTransaction ()->isEquivalent (*tpTrans->getSTransaction ()))
|
else if (tpTransNew->getSTransaction ()->isEquivalent (*tpTrans->getSTransaction ()))
|
||||||
{
|
{
|
||||||
if (bSubmit)
|
if (bSubmit)
|
||||||
(void) NetworkOPs::processTransaction (tpTransNew, bAdmin);
|
(void) NetworkOPs::processTransaction (tpTransNew, bAdmin, bFailHard);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -315,7 +315,7 @@ void NetworkOPs::runTransactionQueue ()
|
|||||||
theApp->getIOService ().post (boost::bind (&NetworkOPs::runTransactionQueue, this));
|
theApp->getIOService ().post (boost::bind (&NetworkOPs::runTransactionQueue, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
Transaction::pointer NetworkOPs::processTransaction (Transaction::pointer trans, bool bAdmin, stCallback callback)
|
Transaction::pointer NetworkOPs::processTransaction (Transaction::pointer trans, bool bAdmin, bool bFailHard, stCallback callback)
|
||||||
{
|
{
|
||||||
LoadEvent::autoptr ev = theApp->getJobQueue ().getLoadEventAP (jtTXN_PROC, "ProcessTXN");
|
LoadEvent::autoptr ev = theApp->getJobQueue ().getLoadEventAP (jtTXN_PROC, "ProcessTXN");
|
||||||
|
|
||||||
@@ -345,7 +345,6 @@ Transaction::pointer NetworkOPs::processTransaction (Transaction::pointer trans,
|
|||||||
}
|
}
|
||||||
|
|
||||||
boost::recursive_mutex::scoped_lock sl (theApp->getMasterLock ());
|
boost::recursive_mutex::scoped_lock sl (theApp->getMasterLock ());
|
||||||
Transaction::pointer dbtx = theApp->getMasterTransaction ().fetch (trans->getID (), true);
|
|
||||||
bool didApply;
|
bool didApply;
|
||||||
TER r = mLedgerMaster->doTransaction (trans->getSTransaction (),
|
TER r = mLedgerMaster->doTransaction (trans->getSTransaction (),
|
||||||
bAdmin ? (tapOPEN_LEDGER | tapNO_CHECK_SIGN | tapADMIN) : (tapOPEN_LEDGER | tapNO_CHECK_SIGN), didApply);
|
bAdmin ? (tapOPEN_LEDGER | tapNO_CHECK_SIGN | tapADMIN) : (tapOPEN_LEDGER | tapNO_CHECK_SIGN), didApply);
|
||||||
@@ -386,11 +385,14 @@ Transaction::pointer NetworkOPs::processTransaction (Transaction::pointer trans,
|
|||||||
}
|
}
|
||||||
else if (isTerRetry (r))
|
else if (isTerRetry (r))
|
||||||
{
|
{
|
||||||
// transaction should be held
|
if (!bFailHard)
|
||||||
WriteLog (lsDEBUG, NetworkOPs) << "Transaction should be held: " << r;
|
{
|
||||||
trans->setStatus (HELD);
|
// transaction should be held
|
||||||
theApp->getMasterTransaction ().canonicalize (trans, true);
|
WriteLog (lsDEBUG, NetworkOPs) << "Transaction should be held: " << r;
|
||||||
mLedgerMaster->addHeldTransaction (trans);
|
trans->setStatus (HELD);
|
||||||
|
theApp->getMasterTransaction ().canonicalize (trans, true);
|
||||||
|
mLedgerMaster->addHeldTransaction (trans);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -398,7 +400,7 @@ Transaction::pointer NetworkOPs::processTransaction (Transaction::pointer trans,
|
|||||||
trans->setStatus (INVALID);
|
trans->setStatus (INVALID);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (didApply || (mMode != omFULL))
|
if (didApply || ((mMode != omFULL) && !bFailHard))
|
||||||
{
|
{
|
||||||
std::set<uint64> peers;
|
std::set<uint64> peers;
|
||||||
|
|
||||||
|
|||||||
@@ -133,13 +133,13 @@ public:
|
|||||||
//
|
//
|
||||||
typedef FUNCTION_TYPE<void (Transaction::pointer, TER)> stCallback; // must complete immediately
|
typedef FUNCTION_TYPE<void (Transaction::pointer, TER)> stCallback; // must complete immediately
|
||||||
void submitTransaction (Job&, SerializedTransaction::pointer, stCallback callback = stCallback ());
|
void submitTransaction (Job&, SerializedTransaction::pointer, stCallback callback = stCallback ());
|
||||||
Transaction::pointer submitTransactionSync (Transaction::ref tpTrans, bool bAdmin, bool bSubmit);
|
Transaction::pointer submitTransactionSync (Transaction::ref tpTrans, bool bAdmin, bool bFailHard, bool bSubmit);
|
||||||
|
|
||||||
void runTransactionQueue ();
|
void runTransactionQueue ();
|
||||||
Transaction::pointer processTransaction (Transaction::pointer, bool bAdmin, stCallback);
|
Transaction::pointer processTransaction (Transaction::pointer, bool bAdmin, bool bFailHard, stCallback);
|
||||||
Transaction::pointer processTransaction (Transaction::pointer transaction, bool bAdmin)
|
Transaction::pointer processTransaction (Transaction::pointer transaction, bool bAdmin, bool bFailHard)
|
||||||
{
|
{
|
||||||
return processTransaction (transaction, bAdmin, stCallback ());
|
return processTransaction (transaction, bAdmin, bFailHard, stCallback ());
|
||||||
}
|
}
|
||||||
|
|
||||||
Transaction::pointer findTransactionByID (uint256 const& transactionID);
|
Transaction::pointer findTransactionByID (uint256 const& transactionID);
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ RPCHandler::RPCHandler (NetworkOPs* netOps, InfoSub::pointer infoSub) : mNetOps
|
|||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
Json::Value RPCHandler::transactionSign (Json::Value jvRequest, bool bSubmit, ScopedLock& mlh)
|
Json::Value RPCHandler::transactionSign (Json::Value jvRequest, bool bSubmit, bool bFailHard, ScopedLock& mlh)
|
||||||
{
|
{
|
||||||
mlh.unlock ();
|
mlh.unlock ();
|
||||||
|
|
||||||
@@ -343,7 +343,7 @@ Json::Value RPCHandler::transactionSign (Json::Value jvRequest, bool bSubmit, Sc
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
// FIXME: For performance, should use asynch interface
|
// FIXME: For performance, should use asynch interface
|
||||||
tpTrans = mNetOps->submitTransactionSync (tpTrans, mRole == ADMIN, bSubmit);
|
tpTrans = mNetOps->submitTransactionSync (tpTrans, mRole == ADMIN, bFailHard, bSubmit);
|
||||||
|
|
||||||
if (!tpTrans)
|
if (!tpTrans)
|
||||||
{
|
{
|
||||||
@@ -1653,7 +1653,8 @@ Json::Value RPCHandler::doRipplePathFind (Json::Value jvRequest, int& cost, Scop
|
|||||||
Json::Value RPCHandler::doSign (Json::Value jvRequest, int& cost, ScopedLock& MasterLockHolder)
|
Json::Value RPCHandler::doSign (Json::Value jvRequest, int& cost, ScopedLock& MasterLockHolder)
|
||||||
{
|
{
|
||||||
cost = rpcCOST_EXPENSIVE;
|
cost = rpcCOST_EXPENSIVE;
|
||||||
return transactionSign (jvRequest, false, MasterLockHolder);
|
bool bFailHard = jvRequest.isMember ("fail_hard") && jvRequest["fail_hard"].asBool ();
|
||||||
|
return transactionSign (jvRequest, false, bFailHard, MasterLockHolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
// {
|
// {
|
||||||
@@ -1664,7 +1665,8 @@ Json::Value RPCHandler::doSubmit (Json::Value jvRequest, int& cost, ScopedLock&
|
|||||||
{
|
{
|
||||||
if (!jvRequest.isMember ("tx_blob"))
|
if (!jvRequest.isMember ("tx_blob"))
|
||||||
{
|
{
|
||||||
return transactionSign (jvRequest, true, MasterLockHolder);
|
bool bFailHard = jvRequest.isMember ("fail_hard") && jvRequest["fail_hard"].asBool ();
|
||||||
|
return transactionSign (jvRequest, true, bFailHard, MasterLockHolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
Json::Value jvResult;
|
Json::Value jvResult;
|
||||||
@@ -1711,7 +1713,8 @@ Json::Value RPCHandler::doSubmit (Json::Value jvRequest, int& cost, ScopedLock&
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
(void) mNetOps->processTransaction (tpTrans, mRole == ADMIN);
|
(void) mNetOps->processTransaction (tpTrans, mRole == ADMIN,
|
||||||
|
jvRequest.isMember ("fail_hard") && jvRequest["fail_hard"].asBool ());
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ class RPCHandler
|
|||||||
// Utilities
|
// Utilities
|
||||||
void addSubmitPath (Json::Value& txJSON);
|
void addSubmitPath (Json::Value& txJSON);
|
||||||
boost::unordered_set<RippleAddress> parseAccountIds (const Json::Value& jvArray);
|
boost::unordered_set<RippleAddress> parseAccountIds (const Json::Value& jvArray);
|
||||||
Json::Value transactionSign (Json::Value jvRequest, bool bSubmit, ScopedLock& mlh);
|
Json::Value transactionSign (Json::Value jvRequest, bool bSubmit, bool bFailHard, ScopedLock& mlh);
|
||||||
|
|
||||||
Json::Value lookupLedger (Json::Value jvRequest, Ledger::pointer& lpLedger);
|
Json::Value lookupLedger (Json::Value jvRequest, Ledger::pointer& lpLedger);
|
||||||
|
|
||||||
|
|||||||
@@ -1081,7 +1081,7 @@ static void checkTransaction (Job&, int flags, SerializedTransaction::pointer st
|
|||||||
else
|
else
|
||||||
theApp->getHashRouter ().setFlag (stx->getTransactionID (), SF_SIGGOOD);
|
theApp->getHashRouter ().setFlag (stx->getTransactionID (), SF_SIGGOOD);
|
||||||
|
|
||||||
theApp->getOPs ().processTransaction (tx, isSetBit (flags, SF_TRUSTED));
|
theApp->getOPs ().processTransaction (tx, isSetBit (flags, SF_TRUSTED), false);
|
||||||
|
|
||||||
#ifndef TRUST_NETWORK
|
#ifndef TRUST_NETWORK
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user