/ src / test / rpc_tests.cpp
rpc_tests.cpp
  1  // Copyright (c) 2012-2022 The Bitcoin Core developers
  2  // Distributed under the MIT software license, see the accompanying
  3  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
  4  
  5  #include <core_io.h>
  6  #include <interfaces/chain.h>
  7  #include <node/context.h>
  8  #include <rpc/blockchain.h>
  9  #include <rpc/client.h>
 10  #include <rpc/server.h>
 11  #include <rpc/util.h>
 12  #include <test/util/setup_common.h>
 13  #include <univalue.h>
 14  #include <util/time.h>
 15  
 16  #include <any>
 17  
 18  #include <boost/test/unit_test.hpp>
 19  
 20  static UniValue JSON(std::string_view json)
 21  {
 22      UniValue value;
 23      BOOST_CHECK(value.read(json));
 24      return value;
 25  }
 26  
 27  class HasJSON
 28  {
 29  public:
 30      explicit HasJSON(std::string json) : m_json(std::move(json)) {}
 31      bool operator()(const UniValue& value) const
 32      {
 33          std::string json{value.write()};
 34          BOOST_CHECK_EQUAL(json, m_json);
 35          return json == m_json;
 36      };
 37  
 38  private:
 39      const std::string m_json;
 40  };
 41  
 42  class RPCTestingSetup : public TestingSetup
 43  {
 44  public:
 45      UniValue TransformParams(const UniValue& params, std::vector<std::pair<std::string, bool>> arg_names) const;
 46      UniValue CallRPC(std::string args);
 47  };
 48  
 49  UniValue RPCTestingSetup::TransformParams(const UniValue& params, std::vector<std::pair<std::string, bool>> arg_names) const
 50  {
 51      UniValue transformed_params;
 52      CRPCTable table;
 53      CRPCCommand command{"category", "method", [&](const JSONRPCRequest& request, UniValue&, bool) -> bool { transformed_params = request.params; return true; }, arg_names, /*unique_id=*/0};
 54      table.appendCommand("method", &command);
 55      JSONRPCRequest request;
 56      request.strMethod = "method";
 57      request.params = params;
 58      if (RPCIsInWarmup(nullptr)) SetRPCWarmupFinished();
 59      table.execute(request);
 60      return transformed_params;
 61  }
 62  
 63  UniValue RPCTestingSetup::CallRPC(std::string args)
 64  {
 65      std::vector<std::string> vArgs{SplitString(args, ' ')};
 66      std::string strMethod = vArgs[0];
 67      vArgs.erase(vArgs.begin());
 68      JSONRPCRequest request;
 69      request.context = &m_node;
 70      request.strMethod = strMethod;
 71      request.params = RPCConvertValues(strMethod, vArgs);
 72      if (RPCIsInWarmup(nullptr)) SetRPCWarmupFinished();
 73      try {
 74          UniValue result = tableRPC.execute(request);
 75          return result;
 76      }
 77      catch (const UniValue& objError) {
 78          throw std::runtime_error(objError.find_value("message").get_str());
 79      }
 80  }
 81  
 82  
 83  BOOST_FIXTURE_TEST_SUITE(rpc_tests, RPCTestingSetup)
 84  
 85  BOOST_AUTO_TEST_CASE(rpc_namedparams)
 86  {
 87      const std::vector<std::pair<std::string, bool>> arg_names{{"arg1", false}, {"arg2", false}, {"arg3", false}, {"arg4", false}, {"arg5", false}};
 88  
 89      // Make sure named arguments are transformed into positional arguments in correct places separated by nulls
 90      BOOST_CHECK_EQUAL(TransformParams(JSON(R"({"arg2": 2, "arg4": 4})"), arg_names).write(), "[null,2,null,4]");
 91  
 92      // Make sure named argument specified multiple times raises an exception
 93      BOOST_CHECK_EXCEPTION(TransformParams(JSON(R"({"arg2": 2, "arg2": 4})"), arg_names), UniValue,
 94                            HasJSON(R"({"code":-8,"message":"Parameter arg2 specified multiple times"})"));
 95  
 96      // Make sure named and positional arguments can be combined.
 97      BOOST_CHECK_EQUAL(TransformParams(JSON(R"({"arg5": 5, "args": [1, 2], "arg4": 4})"), arg_names).write(), "[1,2,null,4,5]");
 98  
 99      // Make sure a unknown named argument raises an exception
100      BOOST_CHECK_EXCEPTION(TransformParams(JSON(R"({"arg2": 2, "unknown": 6})"), arg_names), UniValue,
101                            HasJSON(R"({"code":-8,"message":"Unknown named parameter unknown"})"));
102  
103      // Make sure an overlap between a named argument and positional argument raises an exception
104      BOOST_CHECK_EXCEPTION(TransformParams(JSON(R"({"args": [1,2,3], "arg4": 4, "arg2": 2})"), arg_names), UniValue,
105                            HasJSON(R"({"code":-8,"message":"Parameter arg2 specified twice both as positional and named argument"})"));
106  
107      // Make sure extra positional arguments can be passed through to the method implementation, as long as they don't overlap with named arguments.
108      BOOST_CHECK_EQUAL(TransformParams(JSON(R"({"args": [1,2,3,4,5,6,7,8,9,10]})"), arg_names).write(), "[1,2,3,4,5,6,7,8,9,10]");
109      BOOST_CHECK_EQUAL(TransformParams(JSON(R"([1,2,3,4,5,6,7,8,9,10])"), arg_names).write(), "[1,2,3,4,5,6,7,8,9,10]");
110  }
111  
112  BOOST_AUTO_TEST_CASE(rpc_namedonlyparams)
113  {
114      const std::vector<std::pair<std::string, bool>> arg_names{{"arg1", false}, {"arg2", false}, {"opt1", true}, {"opt2", true}, {"options", false}};
115  
116      // Make sure optional parameters are really optional.
117      BOOST_CHECK_EQUAL(TransformParams(JSON(R"({"arg1": 1, "arg2": 2})"), arg_names).write(), "[1,2]");
118  
119      // Make sure named-only parameters are passed as options.
120      BOOST_CHECK_EQUAL(TransformParams(JSON(R"({"arg1": 1, "arg2": 2, "opt1": 10, "opt2": 20})"), arg_names).write(), R"([1,2,{"opt1":10,"opt2":20}])");
121  
122      // Make sure options can be passed directly.
123      BOOST_CHECK_EQUAL(TransformParams(JSON(R"({"arg1": 1, "arg2": 2, "options":{"opt1": 10, "opt2": 20}})"), arg_names).write(), R"([1,2,{"opt1":10,"opt2":20}])");
124  
125      // Make sure options and named parameters conflict.
126      BOOST_CHECK_EXCEPTION(TransformParams(JSON(R"({"arg1": 1, "arg2": 2, "opt1": 10, "options":{"opt1": 10}})"), arg_names), UniValue,
127                            HasJSON(R"({"code":-8,"message":"Parameter options conflicts with parameter opt1"})"));
128  
129      // Make sure options object specified through args array conflicts.
130      BOOST_CHECK_EXCEPTION(TransformParams(JSON(R"({"args": [1, 2, {"opt1": 10}], "opt2": 20})"), arg_names), UniValue,
131                            HasJSON(R"({"code":-8,"message":"Parameter options specified twice both as positional and named argument"})"));
132  }
133  
134  BOOST_AUTO_TEST_CASE(rpc_rawparams)
135  {
136      // Test raw transaction API argument handling
137      UniValue r;
138  
139      BOOST_CHECK_THROW(CallRPC("getrawtransaction"), std::runtime_error);
140      BOOST_CHECK_THROW(CallRPC("getrawtransaction not_hex"), std::runtime_error);
141      BOOST_CHECK_THROW(CallRPC("getrawtransaction a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff150ed not_int"), std::runtime_error);
142  
143      BOOST_CHECK_THROW(CallRPC("createrawtransaction"), std::runtime_error);
144      BOOST_CHECK_THROW(CallRPC("createrawtransaction null null"), std::runtime_error);
145      BOOST_CHECK_THROW(CallRPC("createrawtransaction not_array"), std::runtime_error);
146      BOOST_CHECK_THROW(CallRPC("createrawtransaction {} {}"), std::runtime_error);
147      BOOST_CHECK_NO_THROW(CallRPC("createrawtransaction [] {}"));
148      BOOST_CHECK_THROW(CallRPC("createrawtransaction [] {} extra"), std::runtime_error);
149  
150      BOOST_CHECK_THROW(CallRPC("decoderawtransaction"), std::runtime_error);
151      BOOST_CHECK_THROW(CallRPC("decoderawtransaction null"), std::runtime_error);
152      BOOST_CHECK_THROW(CallRPC("decoderawtransaction DEADBEEF"), std::runtime_error);
153      std::string rawtx = "0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000";
154      BOOST_CHECK_NO_THROW(r = CallRPC(std::string("decoderawtransaction ")+rawtx));
155      BOOST_CHECK_EQUAL(r.get_obj().find_value("size").getInt<int>(), 193);
156      BOOST_CHECK_EQUAL(r.get_obj().find_value("version").getInt<int>(), 1);
157      BOOST_CHECK_EQUAL(r.get_obj().find_value("locktime").getInt<int>(), 0);
158      BOOST_CHECK_THROW(CallRPC(std::string("decoderawtransaction ")+rawtx+" extra"), std::runtime_error);
159      BOOST_CHECK_NO_THROW(r = CallRPC(std::string("decoderawtransaction ")+rawtx+" false"));
160      BOOST_CHECK_THROW(r = CallRPC(std::string("decoderawtransaction ")+rawtx+" false extra"), std::runtime_error);
161  
162      // Only check failure cases for sendrawtransaction, there's no network to send to...
163      BOOST_CHECK_THROW(CallRPC("sendrawtransaction"), std::runtime_error);
164      BOOST_CHECK_THROW(CallRPC("sendrawtransaction null"), std::runtime_error);
165      BOOST_CHECK_THROW(CallRPC("sendrawtransaction DEADBEEF"), std::runtime_error);
166      BOOST_CHECK_THROW(CallRPC(std::string("sendrawtransaction ")+rawtx+" extra"), std::runtime_error);
167  }
168  
169  BOOST_AUTO_TEST_CASE(rpc_togglenetwork)
170  {
171      UniValue r;
172  
173      r = CallRPC("getnetworkinfo");
174      bool netState = r.get_obj().find_value("networkactive").get_bool();
175      BOOST_CHECK_EQUAL(netState, true);
176  
177      BOOST_CHECK_NO_THROW(CallRPC("setnetworkactive false"));
178      r = CallRPC("getnetworkinfo");
179      int numConnection = r.get_obj().find_value("connections").getInt<int>();
180      BOOST_CHECK_EQUAL(numConnection, 0);
181  
182      netState = r.get_obj().find_value("networkactive").get_bool();
183      BOOST_CHECK_EQUAL(netState, false);
184  
185      BOOST_CHECK_NO_THROW(CallRPC("setnetworkactive true"));
186      r = CallRPC("getnetworkinfo");
187      netState = r.get_obj().find_value("networkactive").get_bool();
188      BOOST_CHECK_EQUAL(netState, true);
189  }
190  
191  BOOST_AUTO_TEST_CASE(rpc_rawsign)
192  {
193      UniValue r;
194      // input is a 1-of-2 multisig (so is output):
195      std::string prevout =
196        "[{\"txid\":\"b4cc287e58f87cdae59417329f710f3ecd75a4ee1d2872b7248f50977c8493f3\","
197        "\"vout\":1,\"scriptPubKey\":\"a914b10c9df5f7edf436c697f02f1efdba4cf399615187\","
198        "\"redeemScript\":\"512103debedc17b3df2badbcdd86d5feb4562b86fe182e5998abd8bcd4f122c6155b1b21027e940bb73ab8732bfdf7f9216ecefca5b94d6df834e77e108f68e66f126044c052ae\"}]";
199      r = CallRPC(std::string("createrawtransaction ")+prevout+" "+
200        "{\"3HqAe9LtNBjnsfM4CyYaWTnvCaUYT7v4oZ\":11}");
201      std::string notsigned = r.get_str();
202      std::string privkey1 = "\"KzsXybp9jX64P5ekX1KUxRQ79Jht9uzW7LorgwE65i5rWACL6LQe\"";
203      std::string privkey2 = "\"Kyhdf5LuKTRx4ge69ybABsiUAWjVRK4XGxAKk2FQLp2HjGMy87Z4\"";
204      r = CallRPC(std::string("signrawtransactionwithkey ")+notsigned+" [] "+prevout);
205      BOOST_CHECK(r.get_obj().find_value("complete").get_bool() == false);
206      r = CallRPC(std::string("signrawtransactionwithkey ")+notsigned+" ["+privkey1+","+privkey2+"] "+prevout);
207      BOOST_CHECK(r.get_obj().find_value("complete").get_bool() == true);
208  }
209  
210  BOOST_AUTO_TEST_CASE(rpc_createraw_op_return)
211  {
212      BOOST_CHECK_NO_THROW(CallRPC("createrawtransaction [{\"txid\":\"a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff150ed\",\"vout\":0}] {\"data\":\"68656c6c6f776f726c64\"}"));
213  
214      // Key not "data" (bad address)
215      BOOST_CHECK_THROW(CallRPC("createrawtransaction [{\"txid\":\"a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff150ed\",\"vout\":0}] {\"somedata\":\"68656c6c6f776f726c64\"}"), std::runtime_error);
216  
217      // Bad hex encoding of data output
218      BOOST_CHECK_THROW(CallRPC("createrawtransaction [{\"txid\":\"a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff150ed\",\"vout\":0}] {\"data\":\"12345\"}"), std::runtime_error);
219      BOOST_CHECK_THROW(CallRPC("createrawtransaction [{\"txid\":\"a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff150ed\",\"vout\":0}] {\"data\":\"12345g\"}"), std::runtime_error);
220  
221      // Data 81 bytes long
222      BOOST_CHECK_NO_THROW(CallRPC("createrawtransaction [{\"txid\":\"a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff150ed\",\"vout\":0}] {\"data\":\"010203040506070809101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081\"}"));
223  }
224  
225  BOOST_AUTO_TEST_CASE(rpc_format_monetary_values)
226  {
227      BOOST_CHECK(ValueFromAmount(0LL).write() == "0.00000000");
228      BOOST_CHECK(ValueFromAmount(1LL).write() == "0.00000001");
229      BOOST_CHECK(ValueFromAmount(17622195LL).write() == "0.17622195");
230      BOOST_CHECK(ValueFromAmount(50000000LL).write() == "0.50000000");
231      BOOST_CHECK(ValueFromAmount(89898989LL).write() == "0.89898989");
232      BOOST_CHECK(ValueFromAmount(100000000LL).write() == "1.00000000");
233      BOOST_CHECK(ValueFromAmount(2099999999999990LL).write() == "20999999.99999990");
234      BOOST_CHECK(ValueFromAmount(2099999999999999LL).write() == "20999999.99999999");
235  
236      BOOST_CHECK_EQUAL(ValueFromAmount(0).write(), "0.00000000");
237      BOOST_CHECK_EQUAL(ValueFromAmount((COIN/10000)*123456789).write(), "12345.67890000");
238      BOOST_CHECK_EQUAL(ValueFromAmount(-COIN).write(), "-1.00000000");
239      BOOST_CHECK_EQUAL(ValueFromAmount(-COIN/10).write(), "-0.10000000");
240  
241      BOOST_CHECK_EQUAL(ValueFromAmount(COIN*100000000).write(), "100000000.00000000");
242      BOOST_CHECK_EQUAL(ValueFromAmount(COIN*10000000).write(), "10000000.00000000");
243      BOOST_CHECK_EQUAL(ValueFromAmount(COIN*1000000).write(), "1000000.00000000");
244      BOOST_CHECK_EQUAL(ValueFromAmount(COIN*100000).write(), "100000.00000000");
245      BOOST_CHECK_EQUAL(ValueFromAmount(COIN*10000).write(), "10000.00000000");
246      BOOST_CHECK_EQUAL(ValueFromAmount(COIN*1000).write(), "1000.00000000");
247      BOOST_CHECK_EQUAL(ValueFromAmount(COIN*100).write(), "100.00000000");
248      BOOST_CHECK_EQUAL(ValueFromAmount(COIN*10).write(), "10.00000000");
249      BOOST_CHECK_EQUAL(ValueFromAmount(COIN).write(), "1.00000000");
250      BOOST_CHECK_EQUAL(ValueFromAmount(COIN/10).write(), "0.10000000");
251      BOOST_CHECK_EQUAL(ValueFromAmount(COIN/100).write(), "0.01000000");
252      BOOST_CHECK_EQUAL(ValueFromAmount(COIN/1000).write(), "0.00100000");
253      BOOST_CHECK_EQUAL(ValueFromAmount(COIN/10000).write(), "0.00010000");
254      BOOST_CHECK_EQUAL(ValueFromAmount(COIN/100000).write(), "0.00001000");
255      BOOST_CHECK_EQUAL(ValueFromAmount(COIN/1000000).write(), "0.00000100");
256      BOOST_CHECK_EQUAL(ValueFromAmount(COIN/10000000).write(), "0.00000010");
257      BOOST_CHECK_EQUAL(ValueFromAmount(COIN/100000000).write(), "0.00000001");
258  
259      BOOST_CHECK_EQUAL(ValueFromAmount(std::numeric_limits<CAmount>::max()).write(), "92233720368.54775807");
260      BOOST_CHECK_EQUAL(ValueFromAmount(std::numeric_limits<CAmount>::max() - 1).write(), "92233720368.54775806");
261      BOOST_CHECK_EQUAL(ValueFromAmount(std::numeric_limits<CAmount>::max() - 2).write(), "92233720368.54775805");
262      BOOST_CHECK_EQUAL(ValueFromAmount(std::numeric_limits<CAmount>::max() - 3).write(), "92233720368.54775804");
263      // ...
264      BOOST_CHECK_EQUAL(ValueFromAmount(std::numeric_limits<CAmount>::min() + 3).write(), "-92233720368.54775805");
265      BOOST_CHECK_EQUAL(ValueFromAmount(std::numeric_limits<CAmount>::min() + 2).write(), "-92233720368.54775806");
266      BOOST_CHECK_EQUAL(ValueFromAmount(std::numeric_limits<CAmount>::min() + 1).write(), "-92233720368.54775807");
267      BOOST_CHECK_EQUAL(ValueFromAmount(std::numeric_limits<CAmount>::min()).write(), "-92233720368.54775808");
268  }
269  
270  static UniValue ValueFromString(const std::string& str) noexcept
271  {
272      UniValue value;
273      value.setNumStr(str);
274      return value;
275  }
276  
277  BOOST_AUTO_TEST_CASE(rpc_parse_monetary_values)
278  {
279      BOOST_CHECK_THROW(AmountFromValue(ValueFromString("-0.00000001")), UniValue);
280      BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0")), 0LL);
281      BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.00000000")), 0LL);
282      BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.00000001")), 1LL);
283      BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.17622195")), 17622195LL);
284      BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.5")), 50000000LL);
285      BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.50000000")), 50000000LL);
286      BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.89898989")), 89898989LL);
287      BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("1.00000000")), 100000000LL);
288      BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("20999999.9999999")), 2099999999999990LL);
289      BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("20999999.99999999")), 2099999999999999LL);
290  
291      BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("1e-8")), COIN/100000000);
292      BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.1e-7")), COIN/100000000);
293      BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.01e-6")), COIN/100000000);
294      BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.0000000000000000000000000000000000000000000000000000000000000000000000000001e+68")), COIN/100000000);
295      BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("10000000000000000000000000000000000000000000000000000000000000000e-64")), COIN);
296      BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000e64")), COIN);
297  
298      BOOST_CHECK_THROW(AmountFromValue(ValueFromString("1e-9")), UniValue); //should fail
299      BOOST_CHECK_THROW(AmountFromValue(ValueFromString("0.000000019")), UniValue); //should fail
300      BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.00000001000000")), 1LL); //should pass, cut trailing 0
301      BOOST_CHECK_THROW(AmountFromValue(ValueFromString("19e-9")), UniValue); //should fail
302      BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.19e-6")), 19); //should pass, leading 0 is present
303      BOOST_CHECK_EXCEPTION(AmountFromValue(".19e-6"), UniValue, HasJSON(R"({"code":-3,"message":"Invalid amount"})")); //should fail, no leading 0
304  
305      BOOST_CHECK_THROW(AmountFromValue(ValueFromString("92233720368.54775808")), UniValue); //overflow error
306      BOOST_CHECK_THROW(AmountFromValue(ValueFromString("1e+11")), UniValue); //overflow error
307      BOOST_CHECK_THROW(AmountFromValue(ValueFromString("1e11")), UniValue); //overflow error signless
308      BOOST_CHECK_THROW(AmountFromValue(ValueFromString("93e+9")), UniValue); //overflow error
309  }
310  
311  BOOST_AUTO_TEST_CASE(rpc_ban)
312  {
313      BOOST_CHECK_NO_THROW(CallRPC(std::string("clearbanned")));
314  
315      UniValue r;
316      BOOST_CHECK_NO_THROW(r = CallRPC(std::string("setban 127.0.0.0 add")));
317      BOOST_CHECK_THROW(r = CallRPC(std::string("setban 127.0.0.0:8334")), std::runtime_error); //portnumber for setban not allowed
318      BOOST_CHECK_NO_THROW(r = CallRPC(std::string("listbanned")));
319      UniValue ar = r.get_array();
320      UniValue o1 = ar[0].get_obj();
321      UniValue adr = o1.find_value("address");
322      BOOST_CHECK_EQUAL(adr.get_str(), "127.0.0.0/32");
323      BOOST_CHECK_NO_THROW(CallRPC(std::string("setban 127.0.0.0 remove")));
324      BOOST_CHECK_NO_THROW(r = CallRPC(std::string("listbanned")));
325      ar = r.get_array();
326      BOOST_CHECK_EQUAL(ar.size(), 0U);
327  
328      BOOST_CHECK_NO_THROW(r = CallRPC(std::string("setban 127.0.0.0/24 add 9907731200 true")));
329      BOOST_CHECK_NO_THROW(r = CallRPC(std::string("listbanned")));
330      ar = r.get_array();
331      o1 = ar[0].get_obj();
332      adr = o1.find_value("address");
333      int64_t banned_until{o1.find_value("banned_until").getInt<int64_t>()};
334      BOOST_CHECK_EQUAL(adr.get_str(), "127.0.0.0/24");
335      BOOST_CHECK_EQUAL(banned_until, 9907731200); // absolute time check
336  
337      BOOST_CHECK_NO_THROW(CallRPC(std::string("clearbanned")));
338  
339      auto now = 10'000s;
340      SetMockTime(now);
341      BOOST_CHECK_NO_THROW(r = CallRPC(std::string("setban 127.0.0.0/24 add 200")));
342      SetMockTime(now += 2s);
343      const int64_t time_remaining_expected{198};
344      BOOST_CHECK_NO_THROW(r = CallRPC(std::string("listbanned")));
345      ar = r.get_array();
346      o1 = ar[0].get_obj();
347      adr = o1.find_value("address");
348      banned_until = o1.find_value("banned_until").getInt<int64_t>();
349      const int64_t ban_created{o1.find_value("ban_created").getInt<int64_t>()};
350      const int64_t ban_duration{o1.find_value("ban_duration").getInt<int64_t>()};
351      const int64_t time_remaining{o1.find_value("time_remaining").getInt<int64_t>()};
352      BOOST_CHECK_EQUAL(adr.get_str(), "127.0.0.0/24");
353      BOOST_CHECK_EQUAL(banned_until, time_remaining_expected + now.count());
354      BOOST_CHECK_EQUAL(ban_duration, banned_until - ban_created);
355      BOOST_CHECK_EQUAL(time_remaining, time_remaining_expected);
356  
357      // must throw an exception because 127.0.0.1 is in already banned subnet range
358      BOOST_CHECK_THROW(r = CallRPC(std::string("setban 127.0.0.1 add")), std::runtime_error);
359  
360      BOOST_CHECK_NO_THROW(CallRPC(std::string("setban 127.0.0.0/24 remove")));
361      BOOST_CHECK_NO_THROW(r = CallRPC(std::string("listbanned")));
362      ar = r.get_array();
363      BOOST_CHECK_EQUAL(ar.size(), 0U);
364  
365      BOOST_CHECK_NO_THROW(r = CallRPC(std::string("setban 127.0.0.0/255.255.0.0 add")));
366      BOOST_CHECK_THROW(r = CallRPC(std::string("setban 127.0.1.1 add")), std::runtime_error);
367  
368      BOOST_CHECK_NO_THROW(CallRPC(std::string("clearbanned")));
369      BOOST_CHECK_NO_THROW(r = CallRPC(std::string("listbanned")));
370      ar = r.get_array();
371      BOOST_CHECK_EQUAL(ar.size(), 0U);
372  
373  
374      BOOST_CHECK_THROW(r = CallRPC(std::string("setban test add")), std::runtime_error); //invalid IP
375  
376      //IPv6 tests
377      BOOST_CHECK_NO_THROW(r = CallRPC(std::string("setban FE80:0000:0000:0000:0202:B3FF:FE1E:8329 add")));
378      BOOST_CHECK_NO_THROW(r = CallRPC(std::string("listbanned")));
379      ar = r.get_array();
380      o1 = ar[0].get_obj();
381      adr = o1.find_value("address");
382      BOOST_CHECK_EQUAL(adr.get_str(), "fe80::202:b3ff:fe1e:8329/128");
383  
384      BOOST_CHECK_NO_THROW(CallRPC(std::string("clearbanned")));
385      BOOST_CHECK_NO_THROW(r = CallRPC(std::string("setban 2001:db8::/ffff:fffc:0:0:0:0:0:0 add")));
386      BOOST_CHECK_NO_THROW(r = CallRPC(std::string("listbanned")));
387      ar = r.get_array();
388      o1 = ar[0].get_obj();
389      adr = o1.find_value("address");
390      BOOST_CHECK_EQUAL(adr.get_str(), "2001:db8::/30");
391  
392      BOOST_CHECK_NO_THROW(CallRPC(std::string("clearbanned")));
393      BOOST_CHECK_NO_THROW(r = CallRPC(std::string("setban 2001:4d48:ac57:400:cacf:e9ff:fe1d:9c63/128 add")));
394      BOOST_CHECK_NO_THROW(r = CallRPC(std::string("listbanned")));
395      ar = r.get_array();
396      o1 = ar[0].get_obj();
397      adr = o1.find_value("address");
398      BOOST_CHECK_EQUAL(adr.get_str(), "2001:4d48:ac57:400:cacf:e9ff:fe1d:9c63/128");
399  }
400  
401  BOOST_AUTO_TEST_CASE(rpc_convert_values_generatetoaddress)
402  {
403      UniValue result;
404  
405      BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", {"101", "mkESjLZW66TmHhiFX8MCaBjrhZ543PPh9a"}));
406      BOOST_CHECK_EQUAL(result[0].getInt<int>(), 101);
407      BOOST_CHECK_EQUAL(result[1].get_str(), "mkESjLZW66TmHhiFX8MCaBjrhZ543PPh9a");
408  
409      BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", {"101", "mhMbmE2tE9xzJYCV9aNC8jKWN31vtGrguU"}));
410      BOOST_CHECK_EQUAL(result[0].getInt<int>(), 101);
411      BOOST_CHECK_EQUAL(result[1].get_str(), "mhMbmE2tE9xzJYCV9aNC8jKWN31vtGrguU");
412  
413      BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", {"1", "mkESjLZW66TmHhiFX8MCaBjrhZ543PPh9a", "9"}));
414      BOOST_CHECK_EQUAL(result[0].getInt<int>(), 1);
415      BOOST_CHECK_EQUAL(result[1].get_str(), "mkESjLZW66TmHhiFX8MCaBjrhZ543PPh9a");
416      BOOST_CHECK_EQUAL(result[2].getInt<int>(), 9);
417  
418      BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", {"1", "mhMbmE2tE9xzJYCV9aNC8jKWN31vtGrguU", "9"}));
419      BOOST_CHECK_EQUAL(result[0].getInt<int>(), 1);
420      BOOST_CHECK_EQUAL(result[1].get_str(), "mhMbmE2tE9xzJYCV9aNC8jKWN31vtGrguU");
421      BOOST_CHECK_EQUAL(result[2].getInt<int>(), 9);
422  }
423  
424  BOOST_AUTO_TEST_CASE(rpc_getblockstats_calculate_percentiles_by_weight)
425  {
426      int64_t total_weight = 200;
427      std::vector<std::pair<CAmount, int64_t>> feerates;
428      CAmount result[NUM_GETBLOCKSTATS_PERCENTILES] = { 0 };
429  
430      for (int64_t i = 0; i < 100; i++) {
431          feerates.emplace_back(1 ,1);
432      }
433  
434      for (int64_t i = 0; i < 100; i++) {
435          feerates.emplace_back(2 ,1);
436      }
437  
438      CalculatePercentilesByWeight(result, feerates, total_weight);
439      BOOST_CHECK_EQUAL(result[0], 1);
440      BOOST_CHECK_EQUAL(result[1], 1);
441      BOOST_CHECK_EQUAL(result[2], 1);
442      BOOST_CHECK_EQUAL(result[3], 2);
443      BOOST_CHECK_EQUAL(result[4], 2);
444  
445      // Test with more pairs, and two pairs overlapping 2 percentiles.
446      total_weight = 100;
447      CAmount result2[NUM_GETBLOCKSTATS_PERCENTILES] = { 0 };
448      feerates.clear();
449  
450      feerates.emplace_back(1, 9);
451      feerates.emplace_back(2 , 16); //10th + 25th percentile
452      feerates.emplace_back(4 ,50); //50th + 75th percentile
453      feerates.emplace_back(5 ,10);
454      feerates.emplace_back(9 ,15);  // 90th percentile
455  
456      CalculatePercentilesByWeight(result2, feerates, total_weight);
457  
458      BOOST_CHECK_EQUAL(result2[0], 2);
459      BOOST_CHECK_EQUAL(result2[1], 2);
460      BOOST_CHECK_EQUAL(result2[2], 4);
461      BOOST_CHECK_EQUAL(result2[3], 4);
462      BOOST_CHECK_EQUAL(result2[4], 9);
463  
464      // Same test as above, but one of the percentile-overlapping pairs is split in 2.
465      total_weight = 100;
466      CAmount result3[NUM_GETBLOCKSTATS_PERCENTILES] = { 0 };
467      feerates.clear();
468  
469      feerates.emplace_back(1, 9);
470      feerates.emplace_back(2 , 11); // 10th percentile
471      feerates.emplace_back(2 , 5); // 25th percentile
472      feerates.emplace_back(4 ,50); //50th + 75th percentile
473      feerates.emplace_back(5 ,10);
474      feerates.emplace_back(9 ,15); // 90th percentile
475  
476      CalculatePercentilesByWeight(result3, feerates, total_weight);
477  
478      BOOST_CHECK_EQUAL(result3[0], 2);
479      BOOST_CHECK_EQUAL(result3[1], 2);
480      BOOST_CHECK_EQUAL(result3[2], 4);
481      BOOST_CHECK_EQUAL(result3[3], 4);
482      BOOST_CHECK_EQUAL(result3[4], 9);
483  
484      // Test with one transaction spanning all percentiles.
485      total_weight = 104;
486      CAmount result4[NUM_GETBLOCKSTATS_PERCENTILES] = { 0 };
487      feerates.clear();
488  
489      feerates.emplace_back(1, 100);
490      feerates.emplace_back(2, 1);
491      feerates.emplace_back(3, 1);
492      feerates.emplace_back(3, 1);
493      feerates.emplace_back(999999, 1);
494  
495      CalculatePercentilesByWeight(result4, feerates, total_weight);
496  
497      for (int64_t i = 0; i < NUM_GETBLOCKSTATS_PERCENTILES; i++) {
498          BOOST_CHECK_EQUAL(result4[i], 1);
499      }
500  }
501  
502  // Make sure errors are triggered appropriately if parameters have the same names.
503  BOOST_AUTO_TEST_CASE(check_dup_param_names)
504  {
505      enum ParamType { POSITIONAL, NAMED, NAMED_ONLY };
506      auto make_rpc = [](std::vector<std::tuple<std::string, ParamType>> param_names) {
507          std::vector<RPCArg> params;
508          std::vector<RPCArg> options;
509          auto push_options = [&] { if (!options.empty()) params.emplace_back(strprintf("options%i", params.size()), RPCArg::Type::OBJ_NAMED_PARAMS, RPCArg::Optional::OMITTED, "", std::move(options)); };
510          for (auto& [param_name, param_type] : param_names) {
511              if (param_type == POSITIONAL) {
512                  push_options();
513                  params.emplace_back(std::move(param_name), RPCArg::Type::NUM, RPCArg::Optional::OMITTED, "description");
514              } else {
515                  options.emplace_back(std::move(param_name), RPCArg::Type::NUM, RPCArg::Optional::OMITTED, "description", RPCArgOptions{.also_positional = param_type == NAMED});
516              }
517          }
518          push_options();
519          return RPCHelpMan{"method_name", "description", params, RPCResults{}, RPCExamples{""}};
520      };
521  
522      // No errors if parameter names are unique.
523      make_rpc({{"p1", POSITIONAL}, {"p2", POSITIONAL}});
524      make_rpc({{"p1", POSITIONAL}, {"p2", NAMED}});
525      make_rpc({{"p1", POSITIONAL}, {"p2", NAMED_ONLY}});
526      make_rpc({{"p1", NAMED}, {"p2", POSITIONAL}});
527      make_rpc({{"p1", NAMED}, {"p2", NAMED}});
528      make_rpc({{"p1", NAMED}, {"p2", NAMED_ONLY}});
529      make_rpc({{"p1", NAMED_ONLY}, {"p2", POSITIONAL}});
530      make_rpc({{"p1", NAMED_ONLY}, {"p2", NAMED}});
531      make_rpc({{"p1", NAMED_ONLY}, {"p2", NAMED_ONLY}});
532  
533      // Error if parameters names are duplicates, unless one parameter is
534      // positional and the other is named and .also_positional is true.
535      BOOST_CHECK_THROW(make_rpc({{"p1", POSITIONAL}, {"p1", POSITIONAL}}), NonFatalCheckError);
536      make_rpc({{"p1", POSITIONAL}, {"p1", NAMED}});
537      BOOST_CHECK_THROW(make_rpc({{"p1", POSITIONAL}, {"p1", NAMED_ONLY}}), NonFatalCheckError);
538      make_rpc({{"p1", NAMED}, {"p1", POSITIONAL}});
539      BOOST_CHECK_THROW(make_rpc({{"p1", NAMED}, {"p1", NAMED}}), NonFatalCheckError);
540      BOOST_CHECK_THROW(make_rpc({{"p1", NAMED}, {"p1", NAMED_ONLY}}), NonFatalCheckError);
541      BOOST_CHECK_THROW(make_rpc({{"p1", NAMED_ONLY}, {"p1", POSITIONAL}}), NonFatalCheckError);
542      BOOST_CHECK_THROW(make_rpc({{"p1", NAMED_ONLY}, {"p1", NAMED}}), NonFatalCheckError);
543      BOOST_CHECK_THROW(make_rpc({{"p1", NAMED_ONLY}, {"p1", NAMED_ONLY}}), NonFatalCheckError);
544  
545      // Make sure duplicate aliases are detected too.
546      BOOST_CHECK_THROW(make_rpc({{"p1", POSITIONAL}, {"p2|p1", NAMED_ONLY}}), NonFatalCheckError);
547  }
548  
549  BOOST_AUTO_TEST_CASE(help_example)
550  {
551      // test different argument types
552      const RPCArgList& args = {{"foo", "bar"}, {"b", true}, {"n", 1}};
553      BOOST_CHECK_EQUAL(HelpExampleCliNamed("test", args), "> bitcoin-cli -named test foo=bar b=true n=1\n");
554      BOOST_CHECK_EQUAL(HelpExampleRpcNamed("test", args), "> curl --user myusername --data-binary '{\"jsonrpc\": \"1.0\", \"id\": \"curltest\", \"method\": \"test\", \"params\": {\"foo\":\"bar\",\"b\":true,\"n\":1}}' -H 'content-type: text/plain;' http://127.0.0.1:8332/\n");
555  
556      // test shell escape
557      BOOST_CHECK_EQUAL(HelpExampleCliNamed("test", {{"foo", "b'ar"}}), "> bitcoin-cli -named test foo='b'''ar'\n");
558      BOOST_CHECK_EQUAL(HelpExampleCliNamed("test", {{"foo", "b\"ar"}}), "> bitcoin-cli -named test foo='b\"ar'\n");
559      BOOST_CHECK_EQUAL(HelpExampleCliNamed("test", {{"foo", "b ar"}}), "> bitcoin-cli -named test foo='b ar'\n");
560  
561      // test object params
562      UniValue obj_value(UniValue::VOBJ);
563      obj_value.pushKV("foo", "bar");
564      obj_value.pushKV("b", false);
565      obj_value.pushKV("n", 1);
566      BOOST_CHECK_EQUAL(HelpExampleCliNamed("test", {{"name", obj_value}}), "> bitcoin-cli -named test name='{\"foo\":\"bar\",\"b\":false,\"n\":1}'\n");
567      BOOST_CHECK_EQUAL(HelpExampleRpcNamed("test", {{"name", obj_value}}), "> curl --user myusername --data-binary '{\"jsonrpc\": \"1.0\", \"id\": \"curltest\", \"method\": \"test\", \"params\": {\"name\":{\"foo\":\"bar\",\"b\":false,\"n\":1}}}' -H 'content-type: text/plain;' http://127.0.0.1:8332/\n");
568  
569      // test array params
570      UniValue arr_value(UniValue::VARR);
571      arr_value.push_back("bar");
572      arr_value.push_back(false);
573      arr_value.push_back(1);
574      BOOST_CHECK_EQUAL(HelpExampleCliNamed("test", {{"name", arr_value}}), "> bitcoin-cli -named test name='[\"bar\",false,1]'\n");
575      BOOST_CHECK_EQUAL(HelpExampleRpcNamed("test", {{"name", arr_value}}), "> curl --user myusername --data-binary '{\"jsonrpc\": \"1.0\", \"id\": \"curltest\", \"method\": \"test\", \"params\": {\"name\":[\"bar\",false,1]}}' -H 'content-type: text/plain;' http://127.0.0.1:8332/\n");
576  
577      // test types don't matter for shell
578      BOOST_CHECK_EQUAL(HelpExampleCliNamed("foo", {{"arg", true}}), HelpExampleCliNamed("foo", {{"arg", "true"}}));
579  
580      // test types matter for Rpc
581      BOOST_CHECK_NE(HelpExampleRpcNamed("foo", {{"arg", true}}), HelpExampleRpcNamed("foo", {{"arg", "true"}}));
582  }
583  
584  BOOST_AUTO_TEST_SUITE_END()