rippled
Loading...
Searching...
No Matches
NoRipple_test.cpp
1#include <test/jtx.h>
2
3#include <xrpl/protocol/Feature.h>
4#include <xrpl/protocol/jss.h>
5
6namespace xrpl {
7
8namespace test {
9
11{
12public:
13 void
15 {
16 testcase("Set and clear noripple");
17
18 using namespace jtx;
19 Env env(*this);
20
21 auto const gw = Account("gateway");
22 auto const alice = Account("alice");
23
24 env.fund(XRP(10000), gw, alice);
25
26 auto const USD = gw["USD"];
27
28 Json::Value account_gw;
29 account_gw[jss::account] = gw.human();
30 Json::Value account_alice;
31 account_alice[jss::account] = alice.human();
32
33 for (auto SetOrClear : {true, false})
34 {
35 // Create a trust line with no-ripple flag setting
36 env(trust(gw, USD(100), alice, SetOrClear ? tfSetNoRipple : tfClearNoRipple));
37 env.close();
38
39 // Check no-ripple flag on sender 'gateway'
40 Json::Value lines{env.rpc("json", "account_lines", to_string(account_gw))};
41 auto const& gwLine0 = lines[jss::result][jss::lines][0u];
42 BEAST_EXPECT(gwLine0[jss::no_ripple].asBool() == SetOrClear);
43
44 // Check no-ripple peer flag on destination 'alice'
45 lines = env.rpc("json", "account_lines", to_string(account_alice));
46 auto const& aline0 = lines[jss::result][jss::lines][0u];
47 BEAST_EXPECT(aline0[jss::no_ripple_peer].asBool() == SetOrClear);
48 }
49 }
50
51 void
53 {
54 testcase("Set noripple on a line with negative balance");
55
56 using namespace jtx;
57 auto const gw = Account("gateway");
58 auto const alice = Account("alice");
59 auto const bob = Account("bob");
60 auto const carol = Account("carol");
61
62 Env env(*this, features);
63
64 env.fund(XRP(10000), gw, alice, bob, carol);
65 env.close();
66
67 env.trust(alice["USD"](100), bob);
68 env.trust(bob["USD"](100), carol);
69 env.close();
70
71 // After this payment alice has a -50 USD balance with bob, and
72 // bob has a -50 USD balance with carol. So neither alice nor
73 // bob should be able to clear the noRipple flag.
74 env(pay(alice, carol, carol["USD"](50)), path(bob));
75 env.close();
76
77 TER const terNeg{TER{tecNO_PERMISSION}};
78
79 env(trust(alice, bob["USD"](100), bob, tfSetNoRipple), ter(terNeg));
80 env(trust(bob, carol["USD"](100), carol, tfSetNoRipple), ter(terNeg));
81 env.close();
82
83 Json::Value params;
84 params[jss::source_account] = alice.human();
85 params[jss::destination_account] = carol.human();
86 params[jss::destination_amount] = [] {
87 Json::Value dest_amt;
88 dest_amt[jss::currency] = "USD";
89 dest_amt[jss::value] = "1";
90 dest_amt[jss::issuer] = Account("carol").human();
91 return dest_amt;
92 }();
93
94 auto const resp = env.rpc("json", "ripple_path_find", to_string(params));
95 BEAST_EXPECT(resp[jss::result][jss::alternatives].size() == 1);
96
97 auto getAccountLines = [&env](Account const& acct) {
98 auto const r = jtx::getAccountLines(env, acct);
99 return r[jss::lines];
100 };
101 {
102 auto const aliceLines = getAccountLines(alice);
103 BEAST_EXPECT(aliceLines.size() == 1);
104 BEAST_EXPECT(aliceLines[0u][jss::no_ripple].asBool() == false);
105
106 auto const bobLines = getAccountLines(bob);
107 BEAST_EXPECT(bobLines.size() == 2);
108 BEAST_EXPECT(bobLines[0u][jss::no_ripple].asBool() == false);
109 BEAST_EXPECT(bobLines[1u][jss::no_ripple].asBool() == false);
110 }
111
112 // Now carol sends the 50 USD back to alice. Then alice and
113 // bob can set the noRipple flag.
114 env(pay(carol, alice, alice["USD"](50)), path(bob));
115 env.close();
116
117 env(trust(alice, bob["USD"](100), bob, tfSetNoRipple));
118 env(trust(bob, carol["USD"](100), carol, tfSetNoRipple));
119 env.close();
120 {
121 auto const aliceLines = getAccountLines(alice);
122 BEAST_EXPECT(aliceLines.size() == 1);
123 BEAST_EXPECT(aliceLines[0u].isMember(jss::no_ripple));
124
125 auto const bobLines = getAccountLines(bob);
126 BEAST_EXPECT(bobLines.size() == 2);
127 BEAST_EXPECT(bobLines[0u].isMember(jss::no_ripple_peer));
128 BEAST_EXPECT(bobLines[1u].isMember(jss::no_ripple));
129 }
130 }
131
132 void
134 {
135 testcase("pairwise NoRipple");
136
137 using namespace jtx;
138 Env env(*this, features);
139
140 auto const alice = Account("alice");
141 auto const bob = Account("bob");
142 auto const carol = Account("carol");
143
144 env.fund(XRP(10000), alice, bob, carol);
145
146 env(trust(bob, alice["USD"](100)));
147 env(trust(carol, bob["USD"](100)));
148
149 env(trust(bob, alice["USD"](100), alice, tfSetNoRipple));
150 env(trust(bob, carol["USD"](100), carol, tfSetNoRipple));
151 env.close();
152
153 Json::Value params;
154 params[jss::source_account] = alice.human();
155 params[jss::destination_account] = carol.human();
156 params[jss::destination_amount] = [] {
157 Json::Value dest_amt;
158 dest_amt[jss::currency] = "USD";
159 dest_amt[jss::value] = "1";
160 dest_amt[jss::issuer] = Account("carol").human();
161 return dest_amt;
162 }();
163
164 Json::Value const resp{env.rpc("json", "ripple_path_find", to_string(params))};
165 BEAST_EXPECT(resp[jss::result][jss::alternatives].size() == 0);
166
167 env(pay(alice, carol, bob["USD"](50)), ter(tecPATH_DRY));
168 }
169
170 void
171 testDefaultRipple(FeatureBitset features, unsigned int apiVersion)
172 {
173 testcase(
174 "Set default ripple on an account and check new trustlines "
175 "Version " +
176 std::to_string(apiVersion));
177
178 using namespace jtx;
179 Env env(*this, features);
180
181 auto const gw = Account("gateway");
182 auto const alice = Account("alice");
183 auto const bob = Account("bob");
184
185 env.fund(XRP(10000), gw, noripple(alice, bob));
186
187 env(fset(bob, asfDefaultRipple));
188
189 auto const USD = gw["USD"];
190
191 env(trust(gw, USD(100), alice, 0));
192 env(trust(gw, USD(100), bob, 0));
193 Json::Value params;
194 params[jss::api_version] = apiVersion;
195
196 {
197 params[jss::account] = gw.human();
198 params[jss::peer] = alice.human();
199
200 auto lines = env.rpc("json", "account_lines", to_string(params));
201 auto const& line0 = lines[jss::result][jss::lines][0u];
202 BEAST_EXPECT(line0[jss::no_ripple_peer].asBool() == true);
203 }
204 {
205 params[jss::account] = alice.human();
206 params[jss::peer] = gw.human();
207
208 auto lines = env.rpc("json", "account_lines", to_string(params));
209 auto const& line0 = lines[jss::result][jss::lines][0u];
210 BEAST_EXPECT(line0[jss::no_ripple].asBool() == true);
211 }
212 {
213 params[jss::account] = gw.human();
214 params[jss::peer] = bob.human();
215
216 auto lines = env.rpc("json", "account_lines", to_string(params));
217 auto const& line0 = lines[jss::result][jss::lines][0u];
218 BEAST_EXPECT(line0[jss::no_ripple].asBool() == false);
219 }
220 {
221 params[jss::account] = bob.human();
222 params[jss::peer] = gw.human();
223
224 auto lines = env.rpc("json", "account_lines", to_string(params));
225 auto const& line0 = lines[jss::result][jss::lines][0u];
226 BEAST_EXPECT(line0[jss::no_ripple_peer].asBool() == false);
227 }
228 {
229 // test for transactions
230 {
231 params[jss::account] = bob.human();
232 params[jss::role] = "gateway";
233 params[jss::transactions] = "asdf";
234
235 auto lines = env.rpc("json", "noripple_check", to_string(params));
236 if (apiVersion < 2u)
237 BEAST_EXPECT(lines[jss::result][jss::status] == "success");
238 else
239 BEAST_EXPECT(lines[jss::result][jss::error] == "invalidParams");
240 }
241 }
242 }
243
244 void
245 run() override
246 {
248
249 auto withFeatsTests = [this](FeatureBitset features) {
250 forAllApiVersions([&, this](unsigned testVersion) { testDefaultRipple(features, testVersion); });
251 testNegativeBalance(features);
252 testPairwise(features);
253 };
254 using namespace jtx;
255 auto const sa = testable_amendments();
256 withFeatsTests(sa - featurePermissionedDEX);
257 withFeatsTests(sa);
258 }
259};
260
261BEAST_DEFINE_TESTSUITE(NoRipple, rpc, xrpl);
262
263} // namespace test
264} // namespace xrpl
Represents a JSON value.
Definition json_value.h:130
A testsuite class.
Definition suite.h:51
testcase_t testcase
Memberspace for declaring test cases.
Definition suite.h:147
void testPairwise(FeatureBitset features)
void run() override
Runs the suite.
void testDefaultRipple(FeatureBitset features, unsigned int apiVersion)
void testNegativeBalance(FeatureBitset features)
Immutable cryptographic account descriptor.
Definition Account.h:19
std::string const & human() const
Returns the human readable public key.
Definition Account.h:94
A transaction testing environment.
Definition Env.h:119
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
Definition Env.cpp:98
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
Definition Env.cpp:261
void trust(STAmount const &amount, Account const &account)
Establish trust lines.
Definition Env.cpp:284
Json::Value rpc(unsigned apiVersion, std::unordered_map< std::string, std::string > const &headers, std::string const &cmd, Args &&... args)
Execute an RPC command.
Definition Env.h:792
Add a path.
Definition paths.h:37
Set the expected result code for a JTx The test will fail if the code doesn't match.
Definition rpc.h:15
Set the expected result code for a JTx The test will fail if the code doesn't match.
Definition ter.h:15
Json::Value trust(Account const &account, STAmount const &amount, std::uint32_t flags)
Modify a trust line.
Definition trust.cpp:13
XRP_t const XRP
Converts to XRP Issue or STAmount.
Definition amount.cpp:90
Json::Value pay(AccountID const &account, AccountID const &to, AnyAmount amount)
Create a payment.
Definition pay.cpp:11
FeatureBitset testable_amendments()
Definition Env.h:76
Json::Value fset(Account const &account, std::uint32_t on, std::uint32_t off=0)
Add and/or remove flag.
Definition flags.cpp:10
Json::Value getAccountLines(Env &env, AccountID const &acctId)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:597
constexpr std::uint32_t tfSetNoRipple
Definition TxFlags.h:96
constexpr std::uint32_t asfDefaultRipple
Definition TxFlags.h:64
void forAllApiVersions(Fn const &fn, Args &&... args)
Definition ApiVersion.h:144
constexpr std::uint32_t tfClearNoRipple
Definition TxFlags.h:97
@ tecPATH_DRY
Definition TER.h:275
@ tecNO_PERMISSION
Definition TER.h:286
T to_string(T... args)