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:
JoelKatz
2013-06-18 13:52:52 -07:00
parent 7c871a55dc
commit 898ee39375
5 changed files with 27 additions and 22 deletions

View File

@@ -197,12 +197,12 @@ void NetworkOPs::submitTransaction (Job&, SerializedTransaction::pointer iTrans,
// FIXME: Should submit to job queue
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.
// 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;
tpTrans->getSTransaction ()->add (s);
@@ -217,7 +217,7 @@ Transaction::pointer NetworkOPs::submitTransactionSync (Transaction::ref tpTrans
else if (tpTransNew->getSTransaction ()->isEquivalent (*tpTrans->getSTransaction ()))
{
if (bSubmit)
(void) NetworkOPs::processTransaction (tpTransNew, bAdmin);
(void) NetworkOPs::processTransaction (tpTransNew, bAdmin, bFailHard);
}
else
{
@@ -315,7 +315,7 @@ void NetworkOPs::runTransactionQueue ()
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");
@@ -345,7 +345,6 @@ Transaction::pointer NetworkOPs::processTransaction (Transaction::pointer trans,
}
boost::recursive_mutex::scoped_lock sl (theApp->getMasterLock ());
Transaction::pointer dbtx = theApp->getMasterTransaction ().fetch (trans->getID (), true);
bool didApply;
TER r = mLedgerMaster->doTransaction (trans->getSTransaction (),
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))
{
// transaction should be held
WriteLog (lsDEBUG, NetworkOPs) << "Transaction should be held: " << r;
trans->setStatus (HELD);
theApp->getMasterTransaction ().canonicalize (trans, true);
mLedgerMaster->addHeldTransaction (trans);
if (!bFailHard)
{
// transaction should be held
WriteLog (lsDEBUG, NetworkOPs) << "Transaction should be held: " << r;
trans->setStatus (HELD);
theApp->getMasterTransaction ().canonicalize (trans, true);
mLedgerMaster->addHeldTransaction (trans);
}
}
else
{
@@ -398,7 +400,7 @@ Transaction::pointer NetworkOPs::processTransaction (Transaction::pointer trans,
trans->setStatus (INVALID);
}
if (didApply || (mMode != omFULL))
if (didApply || ((mMode != omFULL) && !bFailHard))
{
std::set<uint64> peers;

View File

@@ -133,13 +133,13 @@ public:
//
typedef FUNCTION_TYPE<void (Transaction::pointer, TER)> stCallback; // must complete immediately
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 ();
Transaction::pointer processTransaction (Transaction::pointer, bool bAdmin, stCallback);
Transaction::pointer processTransaction (Transaction::pointer transaction, bool bAdmin)
Transaction::pointer processTransaction (Transaction::pointer, bool bAdmin, bool bFailHard, stCallback);
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);

View File

@@ -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 ();
@@ -343,7 +343,7 @@ Json::Value RPCHandler::transactionSign (Json::Value jvRequest, bool bSubmit, Sc
try
{
// FIXME: For performance, should use asynch interface
tpTrans = mNetOps->submitTransactionSync (tpTrans, mRole == ADMIN, bSubmit);
tpTrans = mNetOps->submitTransactionSync (tpTrans, mRole == ADMIN, bFailHard, bSubmit);
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)
{
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"))
{
return transactionSign (jvRequest, true, MasterLockHolder);
bool bFailHard = jvRequest.isMember ("fail_hard") && jvRequest["fail_hard"].asBool ();
return transactionSign (jvRequest, true, bFailHard, MasterLockHolder);
}
Json::Value jvResult;
@@ -1711,7 +1713,8 @@ Json::Value RPCHandler::doSubmit (Json::Value jvRequest, int& cost, ScopedLock&
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)
{

View File

@@ -37,7 +37,7 @@ class RPCHandler
// Utilities
void addSubmitPath (Json::Value& txJSON);
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);

View File

@@ -1081,7 +1081,7 @@ static void checkTransaction (Job&, int flags, SerializedTransaction::pointer st
else
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
}