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