21#include <test/jtx/Env.h>
22#include <test/jtx/envconfig.h>
24#include <xrpld/app/rdb/backend/SQLiteDatabase.h>
25#include <xrpld/rpc/CTID.h>
27#include <xrpl/protocol/ErrorCodes.h>
28#include <xrpl/protocol/STBase.h>
29#include <xrpl/protocol/jss.h>
30#include <xrpl/protocol/serialize.h>
43 using namespace test::jtx;
45 cfg->NETWORK_ID = networkID;
55 using namespace test::jtx;
58 const char* COMMAND = jss::tx.c_str();
59 const char* BINARY = jss::binary.c_str();
62 const char* EXCESSIVE =
65 Env env{*
this, features};
66 auto const alice = Account(
"alice");
67 env.fund(XRP(1000), alice);
72 auto const startLegSeq = env.current()->info().seq;
73 for (
int i = 0; i < 750; ++i)
79 env.closed()->txRead(env.tx()->getTransactionID()).second);
81 auto const endLegSeq = env.closed()->info().seq;
84 for (
size_t i = 0; i < txns.
size(); ++i)
86 auto const& tx = txns[i];
87 auto const& meta = metas[i];
88 auto const result = env.rpc(
95 BEAST_EXPECT(result[jss::result][jss::status] == jss::success);
97 result[jss::result][jss::tx] ==
98 strHex(tx->getSerializer().getData()));
100 result[jss::result][jss::meta] ==
101 strHex(meta->getSerializer().getData()));
104 auto const tx = env.jt(
noop(alice), seq(env.seq(alice))).stx;
105 for (
int deltaEndSeq = 0; deltaEndSeq < 2; ++deltaEndSeq)
107 auto const result = env.rpc(
115 result[jss::result][jss::status] == jss::error &&
116 result[jss::result][jss::error] == NOT_FOUND);
119 BEAST_EXPECT(!result[jss::result][jss::searched_all].asBool());
121 BEAST_EXPECT(result[jss::result][jss::searched_all].asBool());
125 for (
auto&& tx : txns)
127 auto const result = env.rpc(
134 BEAST_EXPECT(result[jss::result][jss::status] == jss::success);
135 BEAST_EXPECT(!result[jss::result][jss::searched_all].asBool());
138 const auto deletedLedger = (startLegSeq + endLegSeq) / 2;
142 ->deleteTransactionByLedgerSeq(deletedLedger);
145 for (
int deltaEndSeq = 0; deltaEndSeq < 2; ++deltaEndSeq)
147 auto const result = env.rpc(
155 result[jss::result][jss::status] == jss::error &&
156 result[jss::result][jss::error] == NOT_FOUND);
157 BEAST_EXPECT(!result[jss::result][jss::searched_all].asBool());
163 auto const result = env.rpc(
170 result[jss::result][jss::status] == jss::error &&
171 result[jss::result][jss::error] == NOT_FOUND);
173 BEAST_EXPECT(!result[jss::result][jss::searched_all].asBool());
179 auto const result = env.rpc(
186 result[jss::result][jss::status] == jss::error &&
187 result[jss::result][jss::error] == NOT_FOUND);
189 BEAST_EXPECT(result[jss::result][jss::searched_all].asBool());
195 auto const result = env.rpc(
201 BEAST_EXPECT(result[jss::result][jss::status] == jss::success);
202 BEAST_EXPECT(!result[jss::result].isMember(jss::searched_all));
207 auto const result = env.rpc(
215 result[jss::result][jss::status] == jss::error &&
216 result[jss::result][jss::error] ==
INVALID);
218 BEAST_EXPECT(!result[jss::result].isMember(jss::searched_all));
223 auto const result = env.rpc(
231 result[jss::result][jss::status] == jss::error &&
232 result[jss::result][jss::error] ==
INVALID);
234 BEAST_EXPECT(!result[jss::result].isMember(jss::searched_all));
239 auto const result = env.rpc(
247 result[jss::result][jss::status] == jss::error &&
248 result[jss::result][jss::error] ==
INVALID);
250 BEAST_EXPECT(!result[jss::result].isMember(jss::searched_all));
255 auto const result = env.rpc(
262 result[jss::result][jss::status] == jss::error &&
263 result[jss::result][jss::error] ==
INVALID);
265 BEAST_EXPECT(!result[jss::result].isMember(jss::searched_all));
270 auto const result = env.rpc(
278 BEAST_EXPECT(result[jss::result][jss::status] == jss::error);
280 BEAST_EXPECT(!result[jss::result].isMember(jss::searched_all));
285 auto const result = env.rpc(
293 result[jss::result][jss::status] == jss::error &&
294 result[jss::result][jss::error] == EXCESSIVE);
296 BEAST_EXPECT(!result[jss::result].isMember(jss::searched_all));
305 using namespace test::jtx;
308 const char* COMMAND = jss::tx.c_str();
309 const char* BINARY = jss::binary.c_str();
312 const char* EXCESSIVE =
316 uint32_t netID = env.app().config().NETWORK_ID;
318 auto const alice = Account(
"alice");
319 env.fund(XRP(1000), alice);
324 auto const startLegSeq = env.current()->info().seq;
325 for (
int i = 0; i < 750; ++i)
331 env.closed()->txRead(env.tx()->getTransactionID()).second);
333 auto const endLegSeq = env.closed()->info().seq;
336 for (
size_t i = 0; i < txns.
size(); ++i)
338 auto const& tx = txns[i];
339 auto const& meta = metas[i];
340 uint32_t txnIdx = meta->getFieldU32(sfTransactionIndex);
341 auto const result = env.rpc(
348 BEAST_EXPECT(result[jss::result][jss::status] == jss::success);
350 result[jss::result][jss::tx] ==
351 strHex(tx->getSerializer().getData()));
353 result[jss::result][jss::meta] ==
354 strHex(meta->getSerializer().getData()));
357 auto const tx = env.jt(
noop(alice), seq(env.seq(alice))).stx;
360 for (
int deltaEndSeq = 0; deltaEndSeq < 2; ++deltaEndSeq)
362 auto const result = env.rpc(
370 result[jss::result][jss::status] == jss::error &&
371 result[jss::result][jss::error] == NOT_FOUND);
374 BEAST_EXPECT(!result[jss::result][jss::searched_all].asBool());
376 BEAST_EXPECT(!result[jss::result][jss::searched_all].asBool());
380 for (
size_t i = 0; i < txns.
size(); ++i)
383 auto const& meta = metas[i];
384 uint32_t txnIdx = meta->getFieldU32(sfTransactionIndex);
385 auto const result = env.rpc(
392 BEAST_EXPECT(result[jss::result][jss::status] == jss::success);
393 BEAST_EXPECT(!result[jss::result][jss::searched_all].asBool());
396 const auto deletedLedger = (startLegSeq + endLegSeq) / 2;
400 ->deleteTransactionByLedgerSeq(deletedLedger);
403 for (
int deltaEndSeq = 0; deltaEndSeq < 2; ++deltaEndSeq)
405 auto const result = env.rpc(
413 result[jss::result][jss::status] == jss::error &&
414 result[jss::result][jss::error] == NOT_FOUND);
415 BEAST_EXPECT(!result[jss::result][jss::searched_all].asBool());
421 auto const result = env.rpc(
425 result[jss::result][jss::status] == jss::error &&
426 result[jss::result][jss::error] == NOT_FOUND);
428 BEAST_EXPECT(!result[jss::result][jss::searched_all].asBool());
434 auto const result = env.rpc(
441 result[jss::result][jss::status] == jss::error &&
442 result[jss::result][jss::error] == NOT_FOUND);
444 BEAST_EXPECT(!result[jss::result][jss::searched_all].asBool());
450 auto const& meta = metas[0];
451 uint32_t txnIdx = meta->getFieldU32(sfTransactionIndex);
452 auto const result = env.rpc(
458 BEAST_EXPECT(result[jss::result][jss::status] == jss::success);
459 BEAST_EXPECT(!result[jss::result].isMember(jss::searched_all));
464 auto const result = env.rpc(
472 result[jss::result][jss::status] == jss::error &&
473 result[jss::result][jss::error] ==
INVALID);
475 BEAST_EXPECT(!result[jss::result].isMember(jss::searched_all));
480 auto const result = env.rpc(
488 result[jss::result][jss::status] == jss::error &&
489 result[jss::result][jss::error] ==
INVALID);
491 BEAST_EXPECT(!result[jss::result].isMember(jss::searched_all));
500 result[jss::result][jss::status] == jss::error &&
501 result[jss::result][jss::error] ==
INVALID);
503 BEAST_EXPECT(!result[jss::result].isMember(jss::searched_all));
508 auto const result = env.rpc(COMMAND, ctid, BINARY,
to_string(20));
511 result[jss::result][jss::status] == jss::error &&
512 result[jss::result][jss::error] ==
INVALID);
514 BEAST_EXPECT(!result[jss::result].isMember(jss::searched_all));
519 auto const result = env.rpc(COMMAND, ctid,
to_string(20));
526 BEAST_EXPECT(result[jss::result][jss::status] == jss::error);
528 BEAST_EXPECT(!result[jss::result].isMember(jss::searched_all));
533 auto const result = env.rpc(
541 result[jss::result][jss::status] == jss::error &&
542 result[jss::result][jss::error] == EXCESSIVE);
544 BEAST_EXPECT(!result[jss::result].isMember(jss::searched_all));
553 using namespace test::jtx;
567 BEAST_EXPECT(
RPC::encodeCTID(13249191UL, 12911U, 65535U) == expected14);
579 auto const expected51 =
583 auto const expected52 =
587 auto const expected53 =
642 using namespace test::jtx;
645 for (uint32_t netID : {11111, 65535, 65536})
648 BEAST_EXPECT(netID == env.app().config().NETWORK_ID);
650 auto const alice = Account(
"alice");
651 auto const bob = Account(
"bob");
653 auto const startLegSeq = env.current()->info().seq;
654 env.fund(XRP(10000), alice, bob);
655 env(pay(alice, bob, XRP(10)));
662 BEAST_EXPECT(ctid == std::nullopt);
667 jsonTx[jss::binary] =
false;
668 jsonTx[jss::ctid] = *ctid;
671 env.rpc(
"json",
"tx",
to_string(jsonTx))[jss::result];
672 BEAST_EXPECT(jrr[jss::ctid] == ctid);
673 BEAST_EXPECT(jrr.isMember(jss::hash));
681 Account
const alice = Account(
"alice");
682 Account
const bob = Account(
"bob");
685 env.fund(XRP(10000), alice, bob);
686 env(pay(alice, bob, XRP(10)));
690 auto isUpper = [](
char c) {
return std::isupper(c) != 0; };
701 mixedCase.
begin(), mixedCase.
end(), isUpper);
702 *iter = std::tolower(*iter);
704 BEAST_EXPECT(ctid != mixedCase);
707 jsonTx[jss::binary] =
false;
708 jsonTx[jss::ctid] = mixedCase;
711 env.rpc(
"json",
"tx",
to_string(jsonTx))[jss::result];
712 BEAST_EXPECT(jrr[jss::ctid] == ctid);
713 BEAST_EXPECT(jrr[jss::hash]);
720 for (uint32_t netID : {2, 1024, 65535, 65536})
723 BEAST_EXPECT(netID == env.app().config().NETWORK_ID);
725 auto const alice = Account(
"alice");
726 auto const bob = Account(
"bob");
728 env.fund(XRP(10000), alice, bob);
729 env(pay(alice, bob, XRP(10)));
732 auto const ledgerSeq = env.current()->info().seq;
740 params[jss::transaction] = hash;
742 env.rpc(
"json",
"tx",
to_string(params))[jss::result];
743 BEAST_EXPECT(jrr[jss::hash] == hash);
745 BEAST_EXPECT(jrr.isMember(jss::ctid) == (netID <= 0xFFFF));
746 if (jrr.isMember(jss::ctid))
749 BEAST_EXPECT(jrr[jss::ctid] == *ctid);
756 uint32_t netID = env.app().config().NETWORK_ID;
758 auto const alice = Account(
"alice");
759 auto const bob = Account(
"bob");
761 auto const startLegSeq = env.current()->info().seq;
762 env.fund(XRP(10000), alice, bob);
763 env(pay(alice, bob, XRP(10)));
768 jsonTx[jss::binary] =
false;
769 jsonTx[jss::ctid] = ctid;
772 env.rpc(
"json",
"tx",
to_string(jsonTx))[jss::result];
773 BEAST_EXPECT(jrr[jss::error] ==
"wrongNetwork");
776 jrr[jss::error_message] ==
777 "Wrong network. You should submit this request to a node "
778 "running on NetworkID: 21338");
787 using namespace test::jtx;
791 cfg->FEES.reference_fee = 10;
794 Account
const alice{
"alice"};
795 Account
const alie{
"alie"};
796 Account
const gw{
"gw"};
797 auto const USD{gw[
"USD"]};
799 env.fund(XRP(1000000), alice, gw);
806 env(pay(alice, gw, XRP(100)));
811 env.closed()->txRead(env.tx()->getTransactionID()).second;
814 expected[jss::DeliverMax] = expected[jss::Amount];
821 Json::Value const result = {[&env, txn, apiVersion]() {
823 params[jss::transaction] =
to_string(txn->getTransactionID());
824 params[jss::binary] =
false;
825 params[jss::api_version] = apiVersion;
826 return env.client().invoke(
"tx", params);
829 BEAST_EXPECT(result[jss::result][jss::status] == jss::success);
833 result[jss::result][jss::close_time_iso] ==
834 "2000-01-01T00:00:20Z");
836 result[jss::result][jss::hash] ==
838 BEAST_EXPECT(result[jss::result][jss::validated] ==
true);
839 BEAST_EXPECT(result[jss::result][jss::ledger_index] == 4);
841 result[jss::result][jss::ledger_hash] ==
842 "B41882E20F0EC6228417D28B9AE0F33833645D35F6799DFB782AC97FC4BB51"
846 for (
auto memberIt = expected.
begin(); memberIt != expected.
end();
850 auto const& result_transaction =
851 (apiVersion > 1 ? result[jss::result][jss::tx_json]
852 : result[jss::result]);
853 if (BEAST_EXPECT(result_transaction.isMember(name)))
855 auto const received = result_transaction[name];
857 received == *memberIt,
858 "Transaction contains \n\"" + name +
"\": "
872 using namespace test::jtx;
876 cfg->FEES.reference_fee = 10;
879 Account
const alice{
"alice"};
880 Account
const gw{
"gw"};
881 auto const USD{gw[
"USD"]};
883 env.fund(XRP(1000000), alice, gw);
887 "3F8BDE5A5F82C4F4708E5E9255B713E303E6E1A371FD5C7A704AFD1387C23981");
890 env.closed()->txRead(txn->getTransactionID()).second;
895 Json::Value const result = [&env, txn, apiVersion]() {
897 params[jss::transaction] =
to_string(txn->getTransactionID());
898 params[jss::binary] =
true;
899 params[jss::api_version] = apiVersion;
900 return env.client().invoke(
"tx", params);
903 if (BEAST_EXPECT(result[jss::status] ==
"success"))
905 BEAST_EXPECT(result[jss::result][jss::status] ==
"success");
906 BEAST_EXPECT(result[jss::result][jss::validated] ==
true);
908 result[jss::result][jss::hash] ==
910 BEAST_EXPECT(result[jss::result][jss::ledger_index] == 3);
911 BEAST_EXPECT(result[jss::result][jss::ctid] ==
"C000000300030000");
916 result[jss::result][jss::tx_blob] == expected_tx_blob);
918 result[jss::result][jss::meta_blob] == expected_meta_blob);
920 result[jss::result][jss::ledger_hash] ==
921 "2D5150E5A5AA436736A732291E437ABF01BC9E206C2DF3C77C4F856915"
924 result[jss::result][jss::close_time_iso] ==
925 "2000-01-01T00:00:10Z");
929 BEAST_EXPECT(result[jss::result][jss::tx] == expected_tx_blob);
931 result[jss::result][jss::meta] == expected_meta_blob);
932 BEAST_EXPECT(result[jss::result][jss::date] == 10);
941 using namespace test::jtx;
const_iterator begin() const
const_iterator end() const
Value removeMember(const char *key)
Remove and return the named member.
testcase_t testcase
Memberspace for declaring test cases.
void testCTIDValidation(FeatureBitset features)
void run() override
Runs the suite.
void testRangeRequest(FeatureBitset features)
std::unique_ptr< Config > makeNetworkConfig(uint32_t networkID)
void testRequest(FeatureBitset features, unsigned apiVersion)
void testBinaryRequest(unsigned apiVersion)
void testCTIDRPC(FeatureBitset features)
void testRangeCTIDRequest(FeatureBitset features)
void testWithFeats(FeatureBitset features)
T emplace_back(T... args)
@ objectValue
object value (collection of name/value pairs).
std::optional< std::tuple< uint32_t, uint16_t, uint16_t > > decodeCTID(const T ctid) noexcept
std::optional< std::string > encodeCTID(uint32_t ledgerSeq, uint32_t txnIndex, uint32_t networkID) noexcept
ErrorInfo const & get_error_info(error_code_i code)
Returns an ErrorInfo that reflects the error code.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
std::string serializeHex(STObject const &o)
Serialize an object to a hex string.
std::string strHex(FwdIt begin, FwdIt end)
void forAllApiVersions(Fn const &fn, Args &&... args)
std::string to_string(base_uint< Bits, Tag > const &a)