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 ripple {
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},
73 test::Path{XRP, A2["JPY"], A2},
74 test::Path{A6, XRP, A2["JPY"], A2}};
75
76 env(pay(A1, A1, A2["JPY"](1000)),
77 json(payPaths.json()),
78 txflags(tfPartialPayment),
79 sendmax(A3["CNY"](56)));
80 env.close();
81
82 Json::Value jrq2;
83 jrq2[jss::binary] = false;
84 jrq2[jss::transaction] =
85 env.tx()->getJson(JsonOptions::none)[jss::hash];
86 jrq2[jss::id] = 3;
87 auto jrr = env.rpc("json", "tx", to_string(jrq2))[jss::result];
88 uint64_t fee{jrr[jss::Fee].asUInt()};
89 auto meta = jrr[jss::meta];
90 uint64_t sumPrev{0};
91 uint64_t sumFinal{0};
92 BEAST_EXPECT(meta[sfAffectedNodes.fieldName].size() == 9);
93 for (auto const& an : meta[sfAffectedNodes.fieldName])
94 {
95 Json::Value node;
96 if (an.isMember(sfCreatedNode.fieldName))
97 node = an[sfCreatedNode.fieldName];
98 else if (an.isMember(sfModifiedNode.fieldName))
99 node = an[sfModifiedNode.fieldName];
100 else if (an.isMember(sfDeletedNode.fieldName))
101 node = an[sfDeletedNode.fieldName];
102
103 if (node && node[sfLedgerEntryType.fieldName] == jss::AccountRoot)
104 {
105 Json::Value prevFields =
106 node.isMember(sfPreviousFields.fieldName)
107 ? node[sfPreviousFields.fieldName]
108 : node[sfNewFields.fieldName];
109 Json::Value finalFields = node.isMember(sfFinalFields.fieldName)
110 ? node[sfFinalFields.fieldName]
111 : node[sfNewFields.fieldName];
112 if (prevFields)
113 sumPrev += beast::lexicalCastThrow<std::uint64_t>(
114 prevFields[sfBalance.fieldName].asString());
115 if (finalFields)
116 sumFinal += beast::lexicalCastThrow<std::uint64_t>(
117 finalFields[sfBalance.fieldName].asString());
118 }
119 }
120 // the difference in balances (final and prev) should be the
121 // fee charged
122 BEAST_EXPECT(sumPrev - sumFinal == fee);
123 }
124
125public:
126 void
127 run() override
128 {
129 using namespace test::jtx;
130 auto const sa = testable_amendments();
131 testXRPDiscrepancy(sa - featurePermissionedDEX);
133 }
134};
135
136BEAST_DEFINE_TESTSUITE(Discrepancy, app, ripple);
137
138} // namespace ripple
Represents a JSON value.
Definition json_value.h:130
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:152
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
constexpr std::uint32_t tfPartialPayment
Definition TxFlags.h:89
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:611