rippled
AmendmentBlocked_test.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2017 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/app/misc/NetworkOPs.h>
21 #include <ripple/core/ConfigSections.h>
22 #include <ripple/protocol/ErrorCodes.h>
23 #include <ripple/protocol/jss.h>
24 #include <test/jtx.h>
25 #include <test/jtx/WSClient.h>
26 
27 namespace ripple {
28 
29 class AmendmentBlocked_test : public beast::unit_test::suite
30 {
31  void
33  {
34  using namespace test::jtx;
35  Env env{*this, envconfig([](std::unique_ptr<Config> cfg) {
36  cfg->loadFromString("[" SECTION_SIGNING_SUPPORT "]\ntrue");
37  return cfg;
38  })};
39  auto const gw = Account{"gateway"};
40  auto const USD = gw["USD"];
41  auto const alice = Account{"alice"};
42  auto const bob = Account{"bob"};
43  Account const ali{"ali", KeyType::secp256k1};
44  env.fund(XRP(10000), alice, bob, gw);
45  env.memoize(ali);
46  // This close() ensures that all the accounts get created and their
47  // default ripple flag gets set before the trust lines are created.
48  // Without it, the ordering manages to create alice's trust line with
49  // noRipple set on gw's end. The existing tests pass either way, but
50  // better to do it right.
51  env.close();
52  env.trust(USD(600), alice);
53  env.trust(USD(700), bob);
54  env(pay(gw, alice, USD(70)));
55  env(pay(gw, bob, USD(50)));
56  env.close();
57 
58  auto wsc = test::makeWSClient(env.app().config());
59 
60  auto current = env.current();
61  // ledger_accept
62  auto jr = env.rpc("ledger_accept")[jss::result];
63  BEAST_EXPECT(jr[jss::ledger_current_index] == current->seq() + 1);
64  BEAST_EXPECT(!jr.isMember(jss::warnings));
65 
66  // ledger_current
67  jr = env.rpc("ledger_current")[jss::result];
68  BEAST_EXPECT(jr[jss::ledger_current_index] == current->seq() + 1);
69  BEAST_EXPECT(!jr.isMember(jss::warnings));
70 
71  // owner_info
72  jr = env.rpc("owner_info", alice.human())[jss::result];
73  BEAST_EXPECT(jr.isMember(jss::accepted) && jr.isMember(jss::current));
74  BEAST_EXPECT(!jr.isMember(jss::warnings));
75 
76  // path_find
77  Json::Value pf_req;
78  pf_req[jss::subcommand] = "create";
79  pf_req[jss::source_account] = alice.human();
80  pf_req[jss::destination_account] = bob.human();
81  pf_req[jss::destination_amount] =
82  bob["USD"](20).value().getJson(JsonOptions::none);
83  jr = wsc->invoke("path_find", pf_req)[jss::result];
84  BEAST_EXPECT(
85  jr.isMember(jss::alternatives) && jr[jss::alternatives].isArray() &&
86  jr[jss::alternatives].size() == 1);
87  BEAST_EXPECT(!jr.isMember(jss::warnings));
88 
89  // submit
90  auto jt = env.jt(noop(alice));
91  Serializer s;
92  jt.stx->add(s);
93  jr = env.rpc("submit", strHex(s.slice()))[jss::result];
94  BEAST_EXPECT(
95  jr.isMember(jss::engine_result) &&
96  jr[jss::engine_result] == "tesSUCCESS");
97  BEAST_EXPECT(!jr.isMember(jss::warnings));
98 
99  // submit_multisigned
100  env(signers(bob, 1, {{alice, 1}}), sig(bob));
101  env(regkey(alice, ali));
102  env.close();
103 
104  Json::Value set_tx;
105  set_tx[jss::Account] = bob.human();
106  set_tx[jss::TransactionType] = jss::AccountSet;
107  set_tx[jss::Fee] = (8 * env.current()->fees().base).jsonClipped();
108  set_tx[jss::Sequence] = env.seq(bob);
109  set_tx[jss::SigningPubKey] = "";
110 
111  Json::Value sign_for;
112  sign_for[jss::tx_json] = set_tx;
113  sign_for[jss::account] = alice.human();
114  sign_for[jss::secret] = ali.name();
115  jr = env.rpc("json", "sign_for", to_string(sign_for))[jss::result];
116  BEAST_EXPECT(jr[jss::status] == "success");
117  BEAST_EXPECT(!jr.isMember(jss::warnings));
118 
119  Json::Value ms_req;
120  ms_req[jss::tx_json] = jr[jss::tx_json];
121  jr = env.rpc(
122  "json", "submit_multisigned", to_string(ms_req))[jss::result];
123  BEAST_EXPECT(
124  jr.isMember(jss::engine_result) &&
125  jr[jss::engine_result] == "tesSUCCESS");
126  BEAST_EXPECT(!jr.isMember(jss::warnings));
127 
128  // set up an amendment warning. Nothing changes
129 
130  env.app().getOPs().setAmendmentWarned();
131 
132  current = env.current();
133  // ledger_accept
134  jr = env.rpc("ledger_accept")[jss::result];
135  BEAST_EXPECT(jr[jss::ledger_current_index] == current->seq() + 1);
136  BEAST_EXPECT(!jr.isMember(jss::warnings));
137 
138  // ledger_current
139  jr = env.rpc("ledger_current")[jss::result];
140  BEAST_EXPECT(jr[jss::ledger_current_index] == current->seq() + 1);
141  BEAST_EXPECT(!jr.isMember(jss::warnings));
142 
143  // owner_info
144  jr = env.rpc("owner_info", alice.human())[jss::result];
145  BEAST_EXPECT(jr.isMember(jss::accepted) && jr.isMember(jss::current));
146  BEAST_EXPECT(!jr.isMember(jss::warnings));
147 
148  // path_find
149  pf_req[jss::subcommand] = "create";
150  pf_req[jss::source_account] = alice.human();
151  pf_req[jss::destination_account] = bob.human();
152  pf_req[jss::destination_amount] =
153  bob["USD"](20).value().getJson(JsonOptions::none);
154  jr = wsc->invoke("path_find", pf_req)[jss::result];
155  BEAST_EXPECT(
156  jr.isMember(jss::alternatives) && jr[jss::alternatives].isArray() &&
157  jr[jss::alternatives].size() == 1);
158  BEAST_EXPECT(!jr.isMember(jss::warnings));
159 
160  // submit
161  jt = env.jt(noop(alice));
162  s.erase();
163  jt.stx->add(s);
164  jr = env.rpc("submit", strHex(s.slice()))[jss::result];
165  BEAST_EXPECT(
166  jr.isMember(jss::engine_result) &&
167  jr[jss::engine_result] == "tesSUCCESS");
168  BEAST_EXPECT(!jr.isMember(jss::warnings));
169 
170  // submit_multisigned
171  env(signers(bob, 1, {{alice, 1}}), sig(bob));
172  env(regkey(alice, ali));
173  env.close();
174 
175  set_tx[jss::Account] = bob.human();
176  set_tx[jss::TransactionType] = jss::AccountSet;
177  set_tx[jss::Fee] = (8 * env.current()->fees().base).jsonClipped();
178  set_tx[jss::Sequence] = env.seq(bob);
179  set_tx[jss::SigningPubKey] = "";
180 
181  sign_for[jss::tx_json] = set_tx;
182  sign_for[jss::account] = alice.human();
183  sign_for[jss::secret] = ali.name();
184  jr = env.rpc("json", "sign_for", to_string(sign_for))[jss::result];
185  BEAST_EXPECT(jr[jss::status] == "success");
186  BEAST_EXPECT(!jr.isMember(jss::warnings));
187 
188  ms_req[jss::tx_json] = jr[jss::tx_json];
189  jr = env.rpc(
190  "json", "submit_multisigned", to_string(ms_req))[jss::result];
191  BEAST_EXPECT(
192  jr.isMember(jss::engine_result) &&
193  jr[jss::engine_result] == "tesSUCCESS");
194  BEAST_EXPECT(!jr.isMember(jss::warnings));
195 
196  // make the network amendment blocked...now all the same
197  // requests should fail
198 
199  env.app().getOPs().setAmendmentBlocked();
200 
201  // ledger_accept
202  jr = env.rpc("ledger_accept")[jss::result];
203  BEAST_EXPECT(
204  jr.isMember(jss::error) && jr[jss::error] == "amendmentBlocked");
205  BEAST_EXPECT(jr[jss::status] == "error");
206  BEAST_EXPECT(!jr.isMember(jss::warnings));
207 
208  // ledger_current
209  jr = env.rpc("ledger_current")[jss::result];
210  BEAST_EXPECT(
211  jr.isMember(jss::error) && jr[jss::error] == "amendmentBlocked");
212  BEAST_EXPECT(jr[jss::status] == "error");
213  BEAST_EXPECT(!jr.isMember(jss::warnings));
214 
215  // owner_info
216  jr = env.rpc("owner_info", alice.human())[jss::result];
217  BEAST_EXPECT(
218  jr.isMember(jss::error) && jr[jss::error] == "amendmentBlocked");
219  BEAST_EXPECT(jr[jss::status] == "error");
220  BEAST_EXPECT(!jr.isMember(jss::warnings));
221 
222  // path_find
223  jr = wsc->invoke("path_find", pf_req)[jss::result];
224  BEAST_EXPECT(
225  jr.isMember(jss::error) && jr[jss::error] == "amendmentBlocked");
226  BEAST_EXPECT(jr[jss::status] == "error");
227  BEAST_EXPECT(!jr.isMember(jss::warnings));
228 
229  // submit
230  jr = env.rpc("submit", strHex(s.slice()))[jss::result];
231  BEAST_EXPECT(
232  jr.isMember(jss::error) && jr[jss::error] == "amendmentBlocked");
233  BEAST_EXPECT(jr[jss::status] == "error");
234  BEAST_EXPECT(!jr.isMember(jss::warnings));
235 
236  // submit_multisigned
237  set_tx[jss::Sequence] = env.seq(bob);
238  sign_for[jss::tx_json] = set_tx;
239  jr = env.rpc("json", "sign_for", to_string(sign_for))[jss::result];
240  BEAST_EXPECT(jr[jss::status] == "success");
241  ms_req[jss::tx_json] = jr[jss::tx_json];
242  jr = env.rpc(
243  "json", "submit_multisigned", to_string(ms_req))[jss::result];
244  BEAST_EXPECT(
245  jr.isMember(jss::error) && jr[jss::error] == "amendmentBlocked");
246  BEAST_EXPECT(!jr.isMember(jss::warnings));
247  }
248 
249 public:
250  void
251  run() override
252  {
254  }
255 };
256 
257 BEAST_DEFINE_TESTSUITE(AmendmentBlocked, app, ripple);
258 
259 } // namespace ripple
ripple::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(AccountTxPaging, app, ripple)
ripple::Serializer::erase
void erase()
Definition: Serializer.h:209
ripple::AmendmentBlocked_test::testBlockedMethods
void testBlockedMethods()
Definition: AmendmentBlocked_test.cpp:32
ripple::AmendmentBlocked_test
Definition: AmendmentBlocked_test.cpp:29
ripple::JsonOptions::none
@ none
ripple::Serializer::slice
Slice slice() const noexcept
Definition: Serializer.h:63
ripple::ValStatus::current
@ current
This was a new validation and was added.
ripple::KeyType::secp256k1
@ secp256k1
ripple::Serializer
Definition: Serializer.h:39
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::test::makeWSClient
std::unique_ptr< WSClient > makeWSClient(Config const &cfg, bool v2, unsigned rpc_version, std::unordered_map< std::string, std::string > const &headers)
Returns a client operating through WebSockets/S.
Definition: WSClient.cpp:300
ripple::to_string
std::string to_string(Manifest const &m)
Format the specified manifest to a string for debugging purposes.
Definition: app/misc/impl/Manifest.cpp:41
ripple::strHex
std::string strHex(FwdIt begin, FwdIt end)
Definition: strHex.h:30
ripple::AmendmentBlocked_test::run
void run() override
Definition: AmendmentBlocked_test.cpp:251
std::unique_ptr
STL class.
Json::Value
Represents a JSON value.
Definition: json_value.h:145