Change how fail_hard transactions are handled.

FIXES: #2847

* Transactions that are submitted with the fail_hard flag
  and that result in any TER code besides tesSUCCESS shall
  be neither queued nor held.

[FOLD] Keep tec results out of the open ledger when fail_hard:

* Improve TransactionStatus const correctness, and remove redundant
  `local` check
* Check open ledger tx count in fail_hard tests
* Fix some wrapping
* Remove duplicate test
This commit is contained in:
Devon White
2019-11-15 13:34:02 -05:00
committed by CJ Cobb
parent 7d867b806d
commit cd9732b47a
7 changed files with 120 additions and 24 deletions

View File

@@ -17,7 +17,6 @@
*/
//==============================================================================
#include <ripple/basics/Log.h>
#include <test/jtx.h>
#include <ripple/json/to_string.h>
#include <ripple/protocol/Feature.h>
@@ -25,6 +24,8 @@
#include <ripple/protocol/TxFlags.h>
#include <ripple/beast/hash/uhash.h>
#include <ripple/beast/unit_test.h>
#include <ripple/app/misc/NetworkOPs.h>
#include <ripple/app/misc/TxQ.h>
#include <boost/lexical_cast.hpp>
#include <boost/optional.hpp>
#include <utility>
@@ -348,6 +349,81 @@ public:
env(noop("alice"));
}
// Rudimentary test to ensure fail_hard
// transactions are neither queued nor
// held.
void
testFailHard()
{
using namespace jtx;
Env env(*this);
auto const gw = Account("gateway");
auto const USD = gw["USD"];
auto const alice = Account {"alice"};
env.fund (XRP(10000), alice);
auto const localTxCnt = env.app().getOPs().getLocalTxCount();
auto const queueTxCount = env.app().getTxQ().getMetrics(*env.current()).txCount;
auto const openTxCount = env.current()->txCount();
BEAST_EXPECT(localTxCnt == 2 && queueTxCount == 0 && openTxCount == 2);
auto applyTxn = [&env](auto&& ...txnArgs)
{
auto jt = env.jt (txnArgs...);
Serializer s;
jt.stx->add (s);
Json::Value args {Json::objectValue};
args[jss::tx_blob] = strHex (s.slice ());
args[jss::fail_hard] = true;
return env.rpc ("json", "submit", args.toStyledString());
};
auto jr = applyTxn(noop (alice), fee (1));
BEAST_EXPECT(jr[jss::result][jss::engine_result] == "telINSUF_FEE_P");
BEAST_EXPECT(env.app().getTxQ().getMetrics(*env.current()).txCount == queueTxCount);
BEAST_EXPECT(env.app().getOPs().getLocalTxCount () == localTxCnt);
BEAST_EXPECT(env.current()->txCount() == openTxCount);
jr = applyTxn(noop (alice), sig("bob"));
BEAST_EXPECT(jr[jss::result][jss::engine_result] == "tefBAD_AUTH");
BEAST_EXPECT(env.app().getTxQ().getMetrics(*env.current()).txCount == queueTxCount);
BEAST_EXPECT(env.app().getOPs().getLocalTxCount () == localTxCnt);
BEAST_EXPECT(env.current()->txCount() == openTxCount);
jr = applyTxn(noop (alice), seq(20));
BEAST_EXPECT(jr[jss::result][jss::engine_result] == "terPRE_SEQ");
BEAST_EXPECT(env.app().getTxQ().getMetrics(*env.current()).txCount == queueTxCount);
BEAST_EXPECT(env.app().getOPs().getLocalTxCount () == localTxCnt);
BEAST_EXPECT(env.current()->txCount() == openTxCount);
jr = applyTxn(offer(alice, XRP(1000), USD(1000)));
BEAST_EXPECT(jr[jss::result][jss::engine_result] == "tecUNFUNDED_OFFER");
BEAST_EXPECT(env.app().getTxQ().getMetrics(*env.current()).txCount == queueTxCount);
BEAST_EXPECT(env.app().getOPs().getLocalTxCount () == localTxCnt);
BEAST_EXPECT(env.current()->txCount() == openTxCount);
jr = applyTxn(noop (alice), fee (drops (-10)));
BEAST_EXPECT(jr[jss::result][jss::engine_result] == "temBAD_FEE");
BEAST_EXPECT(env.app().getTxQ().getMetrics(*env.current()).txCount == queueTxCount);
BEAST_EXPECT(env.app().getOPs().getLocalTxCount () == localTxCnt);
BEAST_EXPECT(env.current()->txCount() == openTxCount);
jr = applyTxn(noop (alice));
BEAST_EXPECT(jr[jss::result][jss::engine_result] == "tesSUCCESS");
BEAST_EXPECT(env.app().getOPs().getLocalTxCount () == localTxCnt + 1);
BEAST_EXPECT(env.current()->txCount() == openTxCount + 1);
}
// Multi-sign basics
void
testMultiSign()
@@ -774,6 +850,7 @@ public:
testRequire();
testKeyType();
testPayments();
testFailHard();
testMultiSign();
testTicket();
testJTxProperties();