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.
31  jtx::Account const& source,
32  jtx::Account const& dest, std::string const& ledger = "")
33  {
35  args[jss::source_account] = source.human();
36  args[jss::destination_account] = dest.human();
37  if (! ledger.empty())
38  args[jss::ledger_index] = ledger;
39  return args;
40  }
41 
42  // Helper function that verifies a deposit_authorized request was
43  // successful and returned the expected value.
45  {
46  Json::Value const& results {result[jss::result]};
47  BEAST_EXPECT (results[jss::deposit_authorized] == authorized);
48  BEAST_EXPECT (results[jss::status] == jss::success);
49  }
50 
51  // Test a variety of non-malformed cases.
52  void testValid()
53  {
54  using namespace jtx;
55  Account const alice {"alice"};
56  Account const becky {"becky"};
57  Account const carol {"carol"};
58 
59  Env env(*this);
60  env.fund(XRP(1000), alice, becky, carol);
61  env.close();
62 
63  // becky is authorized to deposit to herself.
64  validateDepositAuthResult (env.rpc ("json", "deposit_authorized",
66  becky, becky, "validated").toStyledString()), true);
67 
68  // alice should currently be authorized to deposit to becky.
69  validateDepositAuthResult (env.rpc ("json", "deposit_authorized",
71  alice, becky, "validated").toStyledString()), true);
72 
73  // becky sets the DepositAuth flag in the current ledger.
74  env (fset (becky, asfDepositAuth));
75 
76  // alice is no longer authorized to deposit to becky in current ledger.
77  validateDepositAuthResult (env.rpc ("json", "deposit_authorized",
78  depositAuthArgs (alice, becky).toStyledString()), false);
79  env.close();
80 
81  // becky is still authorized to deposit to herself.
82  validateDepositAuthResult (env.rpc ("json", "deposit_authorized",
84  becky, becky, "validated").toStyledString()), true);
85 
86  // It's not a reciprocal arrangement. becky can deposit to alice.
87  validateDepositAuthResult (env.rpc ("json", "deposit_authorized",
89  becky, alice, "current").toStyledString()), true);
90 
91  // becky creates a deposit authorization for alice.
92  env (deposit::auth (becky, alice));
93  env.close();
94 
95  // alice is now authorized to deposit to becky.
96  validateDepositAuthResult (env.rpc ("json", "deposit_authorized",
97  depositAuthArgs (alice, becky, "closed").toStyledString()), true);
98 
99  // carol is still not authorized to deposit to becky.
100  validateDepositAuthResult (env.rpc ("json", "deposit_authorized",
101  depositAuthArgs (carol, becky).toStyledString()), false);
102 
103  // becky clears the the DepositAuth flag so carol becomes authorized.
104  env (fclear (becky, asfDepositAuth));
105  env.close();
106 
107  validateDepositAuthResult (env.rpc ("json", "deposit_authorized",
108  depositAuthArgs (carol, becky).toStyledString()), true);
109 
110  // alice is still authorized to deposit to becky.
111  validateDepositAuthResult (env.rpc ("json", "deposit_authorized",
112  depositAuthArgs (alice, becky).toStyledString()), true);
113  }
114 
115  // Test malformed cases.
116  void testErrors()
117  {
118  using namespace jtx;
119  Account const alice {"alice"};
120  Account const becky {"becky"};
121 
122  // Lambda that checks the (error) result of deposit_authorized.
123  auto verifyErr = [this] (
124  Json::Value const& result, char const* error, char const* errorMsg)
125  {
126  BEAST_EXPECT (result[jss::result][jss::status] == jss::error);
127  BEAST_EXPECT (result[jss::result][jss::error] == error);
128  BEAST_EXPECT (result[jss::result][jss::error_message] == errorMsg);
129  };
130 
131  Env env(*this);
132  {
133  // Missing source_account field.
134  Json::Value args {depositAuthArgs (alice, becky)};
135  args.removeMember (jss::source_account);
136  Json::Value const result {env.rpc (
137  "json", "deposit_authorized", args.toStyledString())};
138  verifyErr (result, "invalidParams",
139  "Missing field 'source_account'.");
140  }
141  {
142  // Non-string source_account field.
143  Json::Value args {depositAuthArgs (alice, becky)};
144  args[jss::source_account] = 7.3;
145  Json::Value const result {env.rpc (
146  "json", "deposit_authorized", args.toStyledString())};
147  verifyErr (result, "invalidParams",
148  "Invalid field 'source_account', not a string.");
149  }
150  {
151  // Corrupt source_account field.
152  Json::Value args {depositAuthArgs (alice, becky)};
153  args[jss::source_account] = "rG1QQv2nh2gr7RCZ!P8YYcBUKCCN633jCn";
154  Json::Value const result {env.rpc (
155  "json", "deposit_authorized", args.toStyledString())};
156  verifyErr (result, "actMalformed", "Account malformed.");
157  }
158  {
159  // Missing destination_account field.
160  Json::Value args {depositAuthArgs (alice, becky)};
161  args.removeMember (jss::destination_account);
162  Json::Value const result {env.rpc (
163  "json", "deposit_authorized", args.toStyledString())};
164  verifyErr (result, "invalidParams",
165  "Missing field 'destination_account'.");
166  }
167  {
168  // Non-string destination_account field.
169  Json::Value args {depositAuthArgs (alice, becky)};
170  args[jss::destination_account] = 7.3;
171  Json::Value const result {env.rpc (
172  "json", "deposit_authorized", args.toStyledString())};
173  verifyErr (result, "invalidParams",
174  "Invalid field 'destination_account', not a string.");
175  }
176  {
177  // Corrupt destination_account field.
178  Json::Value args {depositAuthArgs (alice, becky)};
179  args[jss::destination_account] =
180  "rP6P9ypfAmc!pw8SZHNwM4nvZHFXDraQas";
181  Json::Value const result {env.rpc (
182  "json", "deposit_authorized", args.toStyledString())};
183  verifyErr (result, "actMalformed", "Account malformed.");
184  }
185  {
186  // Request an invalid ledger.
187  Json::Value args {depositAuthArgs (alice, becky, "17")};
188  Json::Value const result {env.rpc (
189  "json", "deposit_authorized", args.toStyledString())};
190  verifyErr (result, "invalidParams", "ledgerIndexMalformed");
191  }
192  {
193  // Request a ledger that doesn't exist yet.
194  Json::Value args {depositAuthArgs (alice, becky)};
195  args[jss::ledger_index] = 17;
196  Json::Value const result {env.rpc (
197  "json", "deposit_authorized", args.toStyledString())};
198  verifyErr (result, "lgrNotFound", "ledgerNotFound");
199  }
200  {
201  // alice is not yet funded.
202  Json::Value args {depositAuthArgs (alice, becky)};
203  Json::Value const result {env.rpc (
204  "json", "deposit_authorized", args.toStyledString())};
205  verifyErr (result, "srcActNotFound",
206  "Source account not found.");
207  }
208  env.fund(XRP(1000), alice);
209  env.close();
210  {
211  // becky is not yet funded.
212  Json::Value args {depositAuthArgs (alice, becky)};
213  Json::Value const result {env.rpc (
214  "json", "deposit_authorized", args.toStyledString())};
215  verifyErr (result, "dstActNotFound",
216  "Destination account not found.");
217  }
218  env.fund(XRP(1000), becky);
219  env.close();
220  {
221  // Once becky is funded try it again and see it succeed.
222  Json::Value args {depositAuthArgs (alice, becky)};
223  Json::Value const result {env.rpc (
224  "json", "deposit_authorized", args.toStyledString())};
225  validateDepositAuthResult (result, true);
226  }
227  }
228 
229  void run() override
230  {
231  testValid();
232  testErrors();
233  }
234 };
235 
236 BEAST_DEFINE_TESTSUITE(DepositAuthorized,app,ripple);
237 
238 }
239 }
240 
ripple::test::jtx::XRP
const XRP_t XRP
Converts to XRP Issue or STAmount.
Definition: amount.cpp:109
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:104
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:45
ripple::authorized
static bool authorized(Port const &port, std::map< std::string, std::string > const &h)
Definition: ServerHandlerImp.cpp:90
ripple::test::DepositAuthorized_test::testValid
void testValid()
Definition: DepositAuthorized_test.cpp:52
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:229
ripple::test::DepositAuthorized_test::testErrors
void testErrors()
Definition: DepositAuthorized_test.cpp:116
ripple::test::jtx::fclear
Json::Value fclear(Account const &account, std::uint32_t off)
Remove account flag.
Definition: flags.h:42
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:936
ripple::test::jtx::Env::close
void close(NetClock::time_point closeTime, boost::optional< std::chrono::milliseconds > consensusDelay=boost::none)
Close and advance the ledger.
Definition: Env.cpp:114
ripple::test::jtx::Env::fund
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
Definition: Env.cpp:214
ripple::test::DepositAuthorized_test::validateDepositAuthResult
void validateDepositAuthResult(Json::Value const &result, bool authorized)
Definition: DepositAuthorized_test.cpp:44
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:30
ripple::test::jtx::Env
A transaction testing environment.
Definition: Env.h:117
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:688
Json::Value
Represents a JSON value.
Definition: json_value.h:141