rippled
Loading...
Searching...
No Matches
Discrepancy_test.cpp
1#include <test/jtx.h>
2#include <test/jtx/Env.h>
3#include <test/jtx/PathSet.h>
4
5#include <xrpl/beast/core/LexicalCast.h>
6#include <xrpl/beast/unit_test.h>
7#include <xrpl/protocol/Feature.h>
8#include <xrpl/protocol/SField.h>
9#include <xrpl/protocol/jss.h>
10
11namespace xrpl {
12
14{
15 // This is a legacy test ported from js/coffee. The ledger
16 // state was originally setup via a saved ledger file and the relevant
17 // entries have since been converted to the equivalent jtx/Env setup.
18 // A payment with path and sendmax is made and the transaction is queried
19 // to verify that the net of balance changes match the fee charged.
20 void
22 {
23 testcase("Discrepancy test : XRP Discrepancy");
24 using namespace test::jtx;
25 Env env{*this, features};
26
27 Account A1{"A1"};
28 Account A2{"A2"};
29 Account A3{"A3"};
30 Account A4{"A4"};
31 Account A5{"A5"};
32 Account A6{"A6"};
33 Account A7{"A7"};
34
35 env.fund(XRP(2000), A1);
36 env.fund(XRP(1000), A2, A6, A7);
37 env.fund(XRP(5000), A3);
38 env.fund(XRP(1000000), A4);
39 env.fund(XRP(600000), A5);
40 env.close();
41
42 env(trust(A1, A3["CNY"](200000)));
43 env(pay(A3, A1, A3["CNY"](31)));
44 env.close();
45
46 env(trust(A1, A2["JPY"](1000000)));
47 env(pay(A2, A1, A2["JPY"](729117)));
48 env.close();
49
50 env(trust(A4, A2["JPY"](10000000)));
51 env(pay(A2, A4, A2["JPY"](470056)));
52 env.close();
53
54 env(trust(A5, A3["CNY"](50000)));
55 env(pay(A3, A5, A3["CNY"](8683)));
56 env.close();
57
58 env(trust(A6, A3["CNY"](3000)));
59 env(pay(A3, A6, A3["CNY"](293)));
60 env.close();
61
62 env(trust(A7, A6["CNY"](50000)));
63 env(pay(A6, A7, A6["CNY"](261)));
64 env.close();
65
66 env(offer(A4, XRP(49147), A2["JPY"](34501)));
67 env(offer(A5, A3["CNY"](3150), XRP(80086)));
68 env(offer(A7, XRP(1233), A6["CNY"](25)));
69 env.close();
70
71 test::PathSet payPaths{
72 test::Path{A2["JPY"], A2}, test::Path{XRP, A2["JPY"], A2}, test::Path{A6, XRP, A2["JPY"], A2}};
73
74 env(pay(A1, A1, A2["JPY"](1000)), json(payPaths.json()), txflags(tfPartialPayment), sendmax(A3["CNY"](56)));
75 env.close();
76
77 Json::Value jrq2;
78 jrq2[jss::binary] = false;
79 jrq2[jss::transaction] = env.tx()->getJson(JsonOptions::none)[jss::hash];
80 jrq2[jss::id] = 3;
81 auto jrr = env.rpc("json", "tx", to_string(jrq2))[jss::result];
82 uint64_t fee{jrr[jss::Fee].asUInt()};
83 auto meta = jrr[jss::meta];
84 uint64_t sumPrev{0};
85 uint64_t sumFinal{0};
86 BEAST_EXPECT(meta[sfAffectedNodes.fieldName].size() == 9);
87 for (auto const& an : meta[sfAffectedNodes.fieldName])
88 {
89 Json::Value node;
90 if (an.isMember(sfCreatedNode.fieldName))
91 node = an[sfCreatedNode.fieldName];
92 else if (an.isMember(sfModifiedNode.fieldName))
93 node = an[sfModifiedNode.fieldName];
94 else if (an.isMember(sfDeletedNode.fieldName))
95 node = an[sfDeletedNode.fieldName];
96
97 if (node && node[sfLedgerEntryType.fieldName] == jss::AccountRoot)
98 {
99 Json::Value prevFields = node.isMember(sfPreviousFields.fieldName) ? node[sfPreviousFields.fieldName]
100 : node[sfNewFields.fieldName];
101 Json::Value finalFields = node.isMember(sfFinalFields.fieldName) ? node[sfFinalFields.fieldName]
102 : node[sfNewFields.fieldName];
103 if (prevFields)
104 sumPrev += beast::lexicalCastThrow<std::uint64_t>(prevFields[sfBalance.fieldName].asString());
105 if (finalFields)
106 sumFinal += beast::lexicalCastThrow<std::uint64_t>(finalFields[sfBalance.fieldName].asString());
107 }
108 }
109 // the difference in balances (final and prev) should be the
110 // fee charged
111 BEAST_EXPECT(sumPrev - sumFinal == fee);
112 }
113
114public:
115 void
116 run() override
117 {
118 using namespace test::jtx;
119 auto const sa = testable_amendments();
120 testXRPDiscrepancy(sa - featurePermissionedDEX);
122 }
123};
124
125BEAST_DEFINE_TESTSUITE(Discrepancy, app, xrpl);
126
127} // namespace xrpl
Represents a JSON value.
Definition json_value.h:131
UInt asUInt() const
std::string asString() const
Returns the unquoted string value.
bool isMember(char const *key) const
Return true if the object has a member named key.
A testsuite class.
Definition suite.h:52
testcase_t testcase
Memberspace for declaring test cases.
Definition suite.h:148
void testXRPDiscrepancy(FeatureBitset features)
void run() override
Runs the suite.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:598
constexpr std::uint32_t tfPartialPayment
Definition TxFlags.h:89