rippled
DepositAuthorized_test.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2018 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #include <ripple/protocol/jss.h>
21 #include <test/jtx.h>
22 
23 namespace ripple {
24 namespace test {
25 
26 class DepositAuthorized_test : public beast::unit_test::suite
27 {
28 public:
29  // Helper function that builds arguments for a deposit_authorized command.
30  static Json::Value
32  jtx::Account const& source,
33  jtx::Account const& dest,
34  std::string const& ledger = "")
35  {
37  args[jss::source_account] = source.human();
38  args[jss::destination_account] = dest.human();
39  if (!ledger.empty())
40  args[jss::ledger_index] = ledger;
41  return args;
42  }
43 
44  // Helper function that verifies a deposit_authorized request was
45  // successful and returned the expected value.
46  void
48  {
49  Json::Value const& results{result[jss::result]};
50  BEAST_EXPECT(results[jss::deposit_authorized] == authorized);
51  BEAST_EXPECT(results[jss::status] == jss::success);
52  }
53 
54  // Test a variety of non-malformed cases.
55  void
57  {
58  using namespace jtx;
59  Account const alice{"alice"};
60  Account const becky{"becky"};
61  Account const carol{"carol"};
62 
63  Env env(*this);
64  env.fund(XRP(1000), alice, becky, carol);
65  env.close();
66 
67  // becky is authorized to deposit to herself.
69  env.rpc(
70  "json",
71  "deposit_authorized",
72  depositAuthArgs(becky, becky, "validated").toStyledString()),
73  true);
74 
75  // alice should currently be authorized to deposit to becky.
77  env.rpc(
78  "json",
79  "deposit_authorized",
80  depositAuthArgs(alice, becky, "validated").toStyledString()),
81  true);
82 
83  // becky sets the DepositAuth flag in the current ledger.
84  env(fset(becky, asfDepositAuth));
85 
86  // alice is no longer authorized to deposit to becky in current ledger.
88  env.rpc(
89  "json",
90  "deposit_authorized",
91  depositAuthArgs(alice, becky).toStyledString()),
92  false);
93  env.close();
94 
95  // becky is still authorized to deposit to herself.
97  env.rpc(
98  "json",
99  "deposit_authorized",
100  depositAuthArgs(becky, becky, "validated").toStyledString()),
101  true);
102 
103  // It's not a reciprocal arrangement. becky can deposit to alice.
105  env.rpc(
106  "json",
107  "deposit_authorized",
108  depositAuthArgs(becky, alice, "current").toStyledString()),
109  true);
110 
111  // becky creates a deposit authorization for alice.
112  env(deposit::auth(becky, alice));
113  env.close();
114 
115  // alice is now authorized to deposit to becky.
117  env.rpc(
118  "json",
119  "deposit_authorized",
120  depositAuthArgs(alice, becky, "closed").toStyledString()),
121  true);
122 
123  // carol is still not authorized to deposit to becky.
125  env.rpc(
126  "json",
127  "deposit_authorized",
128  depositAuthArgs(carol, becky).toStyledString()),
129  false);
130 
131  // becky clears the the DepositAuth flag so carol becomes authorized.
132  env(fclear(becky, asfDepositAuth));
133  env.close();
134 
136  env.rpc(
137  "json",
138  "deposit_authorized",
139  depositAuthArgs(carol, becky).toStyledString()),
140  true);
141 
142  // alice is still authorized to deposit to becky.
144  env.rpc(
145  "json",
146  "deposit_authorized",
147  depositAuthArgs(alice, becky).toStyledString()),
148  true);
149  }
150 
151  // Test malformed cases.
152  void
154  {
155  using namespace jtx;
156  Account const alice{"alice"};
157  Account const becky{"becky"};
158 
159  // Lambda that checks the (error) result of deposit_authorized.
160  auto verifyErr = [this](
161  Json::Value const& result,
162  char const* error,
163  char const* errorMsg) {
164  BEAST_EXPECT(result[jss::result][jss::status] == jss::error);
165  BEAST_EXPECT(result[jss::result][jss::error] == error);
166  BEAST_EXPECT(result[jss::result][jss::error_message] == errorMsg);
167  };
168 
169  Env env(*this);
170  {
171  // Missing source_account field.
172  Json::Value args{depositAuthArgs(alice, becky)};
173  args.removeMember(jss::source_account);
174  Json::Value const result{
175  env.rpc("json", "deposit_authorized", args.toStyledString())};
176  verifyErr(
177  result, "invalidParams", "Missing field 'source_account'.");
178  }
179  {
180  // Non-string source_account field.
181  Json::Value args{depositAuthArgs(alice, becky)};
182  args[jss::source_account] = 7.3;
183  Json::Value const result{
184  env.rpc("json", "deposit_authorized", args.toStyledString())};
185  verifyErr(
186  result,
187  "invalidParams",
188  "Invalid field 'source_account', not a string.");
189  }
190  {
191  // Corrupt source_account field.
192  Json::Value args{depositAuthArgs(alice, becky)};
193  args[jss::source_account] = "rG1QQv2nh2gr7RCZ!P8YYcBUKCCN633jCn";
194  Json::Value const result{
195  env.rpc("json", "deposit_authorized", args.toStyledString())};
196  verifyErr(result, "actMalformed", "Account malformed.");
197  }
198  {
199  // Missing destination_account field.
200  Json::Value args{depositAuthArgs(alice, becky)};
201  args.removeMember(jss::destination_account);
202  Json::Value const result{
203  env.rpc("json", "deposit_authorized", args.toStyledString())};
204  verifyErr(
205  result,
206  "invalidParams",
207  "Missing field 'destination_account'.");
208  }
209  {
210  // Non-string destination_account field.
211  Json::Value args{depositAuthArgs(alice, becky)};
212  args[jss::destination_account] = 7.3;
213  Json::Value const result{
214  env.rpc("json", "deposit_authorized", args.toStyledString())};
215  verifyErr(
216  result,
217  "invalidParams",
218  "Invalid field 'destination_account', not a string.");
219  }
220  {
221  // Corrupt destination_account field.
222  Json::Value args{depositAuthArgs(alice, becky)};
223  args[jss::destination_account] =
224  "rP6P9ypfAmc!pw8SZHNwM4nvZHFXDraQas";
225  Json::Value const result{
226  env.rpc("json", "deposit_authorized", args.toStyledString())};
227  verifyErr(result, "actMalformed", "Account malformed.");
228  }
229  {
230  // Request an invalid ledger.
231  Json::Value args{depositAuthArgs(alice, becky, "17")};
232  Json::Value const result{
233  env.rpc("json", "deposit_authorized", args.toStyledString())};
234  verifyErr(result, "invalidParams", "ledgerIndexMalformed");
235  }
236  {
237  // Request a ledger that doesn't exist yet.
238  Json::Value args{depositAuthArgs(alice, becky)};
239  args[jss::ledger_index] = 17;
240  Json::Value const result{
241  env.rpc("json", "deposit_authorized", args.toStyledString())};
242  verifyErr(result, "lgrNotFound", "ledgerNotFound");
243  }
244  {
245  // alice is not yet funded.
246  Json::Value args{depositAuthArgs(alice, becky)};
247  Json::Value const result{
248  env.rpc("json", "deposit_authorized", args.toStyledString())};
249  verifyErr(result, "srcActNotFound", "Source account not found.");
250  }
251  env.fund(XRP(1000), alice);
252  env.close();
253  {
254  // becky is not yet funded.
255  Json::Value args{depositAuthArgs(alice, becky)};
256  Json::Value const result{
257  env.rpc("json", "deposit_authorized", args.toStyledString())};
258  verifyErr(
259  result, "dstActNotFound", "Destination account not found.");
260  }
261  env.fund(XRP(1000), becky);
262  env.close();
263  {
264  // Once becky is funded try it again and see it succeed.
265  Json::Value args{depositAuthArgs(alice, becky)};
266  Json::Value const result{
267  env.rpc("json", "deposit_authorized", args.toStyledString())};
268  validateDepositAuthResult(result, true);
269  }
270  }
271 
272  void
273  run() override
274  {
275  testValid();
276  testErrors();
277  }
278 };
279 
280 BEAST_DEFINE_TESTSUITE(DepositAuthorized, app, ripple);
281 
282 } // namespace test
283 } // namespace ripple
ripple::test::jtx::XRP
const XRP_t XRP
Converts to XRP Issue or STAmount.
Definition: amount.cpp:105
ripple::test::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(AccountDelete, app, ripple)
std::string
STL class.
ripple::test::jtx::Account::human
std::string const & human() const
Returns the human readable public key.
Definition: Account.h:109
ripple::asfDepositAuth
const std::uint32_t asfDepositAuth
Definition: TxFlags.h:73
Json::objectValue
@ objectValue
object value (collection of name/value pairs).
Definition: json_value.h:43
ripple::authorized
static bool authorized(Port const &port, std::map< std::string, std::string > const &h)
Definition: ServerHandlerImp.cpp:85
ripple::test::DepositAuthorized_test::testValid
void testValid()
Definition: DepositAuthorized_test.cpp:56
ripple::test::jtx::fset
Json::Value fset(Account const &account, std::uint32_t on, std::uint32_t off=0)
Add and/or remove flag.
Definition: flags.cpp:28
ripple::test::DepositAuthorized_test::run
void run() override
Definition: DepositAuthorized_test.cpp:273
ripple::test::DepositAuthorized_test::testErrors
void testErrors()
Definition: DepositAuthorized_test.cpp:153
ripple::test::jtx::fclear
Json::Value fclear(Account const &account, std::uint32_t off)
Remove account flag.
Definition: flags.h:40
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
Json::Value::removeMember
Value removeMember(const char *key)
Remove and return the named member.
Definition: json_value.cpp:907
ripple::test::jtx::Env::close
bool close(NetClock::time_point closeTime, boost::optional< std::chrono::milliseconds > consensusDelay=boost::none)
Close and advance the ledger.
Definition: Env.cpp:111
ripple::test::jtx::Env::fund
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
Definition: Env.cpp:209
ripple::test::DepositAuthorized_test::validateDepositAuthResult
void validateDepositAuthResult(Json::Value const &result, bool authorized)
Definition: DepositAuthorized_test.cpp:47
ripple::test::jtx::Account
Immutable cryptographic account descriptor.
Definition: Account.h:37
ripple::test::DepositAuthorized_test
Definition: DepositAuthorized_test.cpp:26
ripple::test::DepositAuthorized_test::depositAuthArgs
static Json::Value depositAuthArgs(jtx::Account const &source, jtx::Account const &dest, std::string const &ledger="")
Definition: DepositAuthorized_test.cpp:31
ripple::test::jtx::Env
A transaction testing environment.
Definition: Env.h:114
ripple::test::jtx::Env::rpc
Json::Value rpc(std::unordered_map< std::string, std::string > const &headers, std::string const &cmd, Args &&... args)
Execute an RPC command.
Definition: Env.h:682
Json::Value
Represents a JSON value.
Definition: json_value.h:145