1 // Copyright (c) 2012-2018 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 <rpc/server.h>
6 #include <rpc/client.h>
7 #include <rpc/util.h>
8 
9 #include <core_io.h>
10 #include <init.h>
11 #include <interfaces/chain.h>
12 #include <key_io.h>
13 #include <netbase.h>
14 
15 #include <test/test_bitcoin.h>
16 
17 #include <boost/algorithm/string.hpp>
18 #include <boost/test/unit_test.hpp>
19 
20 #include <univalue.h>
21 
22 #include <rpc/blockchain.h>
23 
CallRPC(std::string args)24 UniValue CallRPC(std::string args)
25 {
26     std::vector<std::string> vArgs;
27     boost::split(vArgs, args, boost::is_any_of(" \t"));
28     std::string strMethod = vArgs[0];
29     vArgs.erase(vArgs.begin());
30     JSONRPCRequest request;
31     request.strMethod = strMethod;
32     request.params = RPCConvertValues(strMethod, vArgs);
33     request.fHelp = false;
34     BOOST_CHECK(tableRPC[strMethod]);
35     rpcfn_type method = tableRPC[strMethod]->actor;
36     try {
37         UniValue result = (*method)(request);
38         return result;
39     }
40     catch (const UniValue& objError) {
41         throw std::runtime_error(find_value(objError, "message").get_str());
42     }
43 }
44 
45 
BOOST_FIXTURE_TEST_SUITE(rpc_tests,TestingSetup)46 BOOST_FIXTURE_TEST_SUITE(rpc_tests, TestingSetup)
47 
48 BOOST_AUTO_TEST_CASE(rpc_rawparams)
49 {
50     // Test raw transaction API argument handling
51     UniValue r;
52 
53     BOOST_CHECK_THROW(CallRPC("getrawtransaction"), std::runtime_error);
54     BOOST_CHECK_THROW(CallRPC("getrawtransaction not_hex"), std::runtime_error);
55     BOOST_CHECK_THROW(CallRPC("getrawtransaction a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff150ed not_int"), std::runtime_error);
56 
57     BOOST_CHECK_THROW(CallRPC("createrawtransaction"), std::runtime_error);
58     BOOST_CHECK_THROW(CallRPC("createrawtransaction null null"), std::runtime_error);
59     BOOST_CHECK_THROW(CallRPC("createrawtransaction not_array"), std::runtime_error);
60     BOOST_CHECK_THROW(CallRPC("createrawtransaction {} {}"), std::runtime_error);
61     BOOST_CHECK_NO_THROW(CallRPC("createrawtransaction [] {}"));
62     BOOST_CHECK_THROW(CallRPC("createrawtransaction [] {} extra"), std::runtime_error);
63 
64     BOOST_CHECK_THROW(CallRPC("decoderawtransaction"), std::runtime_error);
65     BOOST_CHECK_THROW(CallRPC("decoderawtransaction null"), std::runtime_error);
66     BOOST_CHECK_THROW(CallRPC("decoderawtransaction DEADBEEF"), std::runtime_error);
67     std::string rawtx = "0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000";
68     BOOST_CHECK_NO_THROW(r = CallRPC(std::string("decoderawtransaction ")+rawtx));
69     BOOST_CHECK_EQUAL(find_value(r.get_obj(), "size").get_int(), 193);
70     BOOST_CHECK_EQUAL(find_value(r.get_obj(), "version").get_int(), 1);
71     BOOST_CHECK_EQUAL(find_value(r.get_obj(), "locktime").get_int(), 0);
72     BOOST_CHECK_THROW(CallRPC(std::string("decoderawtransaction ")+rawtx+" extra"), std::runtime_error);
73     BOOST_CHECK_NO_THROW(r = CallRPC(std::string("decoderawtransaction ")+rawtx+" false"));
74     BOOST_CHECK_THROW(r = CallRPC(std::string("decoderawtransaction ")+rawtx+" false extra"), std::runtime_error);
75 
76     // Only check failure cases for sendrawtransaction, there's no network to send to...
77     BOOST_CHECK_THROW(CallRPC("sendrawtransaction"), std::runtime_error);
78     BOOST_CHECK_THROW(CallRPC("sendrawtransaction null"), std::runtime_error);
79     BOOST_CHECK_THROW(CallRPC("sendrawtransaction DEADBEEF"), std::runtime_error);
80     BOOST_CHECK_THROW(CallRPC(std::string("sendrawtransaction ")+rawtx+" extra"), std::runtime_error);
81 }
82 
BOOST_AUTO_TEST_CASE(rpc_togglenetwork)83 BOOST_AUTO_TEST_CASE(rpc_togglenetwork)
84 {
85     UniValue r;
86 
87     r = CallRPC("getnetworkinfo");
88     bool netState = find_value(r.get_obj(), "networkactive").get_bool();
89     BOOST_CHECK_EQUAL(netState, true);
90 
91     BOOST_CHECK_NO_THROW(CallRPC("setnetworkactive false"));
92     r = CallRPC("getnetworkinfo");
93     int numConnection = find_value(r.get_obj(), "connections").get_int();
94     BOOST_CHECK_EQUAL(numConnection, 0);
95 
96     netState = find_value(r.get_obj(), "networkactive").get_bool();
97     BOOST_CHECK_EQUAL(netState, false);
98 
99     BOOST_CHECK_NO_THROW(CallRPC("setnetworkactive true"));
100     r = CallRPC("getnetworkinfo");
101     netState = find_value(r.get_obj(), "networkactive").get_bool();
102     BOOST_CHECK_EQUAL(netState, true);
103 }
104 
BOOST_AUTO_TEST_CASE(rpc_rawsign)105 BOOST_AUTO_TEST_CASE(rpc_rawsign)
106 {
107     UniValue r;
108     // input is a 1-of-2 multisig (so is output):
109     std::string prevout =
110       "[{\"txid\":\"b4cc287e58f87cdae59417329f710f3ecd75a4ee1d2872b7248f50977c8493f3\","
111       "\"vout\":1,\"scriptPubKey\":\"a914b10c9df5f7edf436c697f02f1efdba4cf399615187\","
112       "\"redeemScript\":\"512103debedc17b3df2badbcdd86d5feb4562b86fe182e5998abd8bcd4f122c6155b1b21027e940bb73ab8732bfdf7f9216ecefca5b94d6df834e77e108f68e66f126044c052ae\"}]";
113     r = CallRPC(std::string("createrawtransaction ")+prevout+" "+
114       "{\"3HqAe9LtNBjnsfM4CyYaWTnvCaUYT7v4oZ\":11}");
115     std::string notsigned = r.get_str();
116     std::string privkey1 = "\"T6hoRM7L8u4f9vHd4eGMAmwV6AMCE11PvYi7YjrdegG223kw64r1\"";
117     std::string privkey2 = "\"T5Xu6pe5iqQYqXGxhcY2QEFr7NNoVQ5R6A4abpswunCTF9w85g8V\"";
118     InitInterfaces interfaces;
119     interfaces.chain = interfaces::MakeChain();
120     g_rpc_interfaces = &interfaces;
121     r = CallRPC(std::string("signrawtransactionwithkey ")+notsigned+" [] "+prevout);
122     BOOST_CHECK(find_value(r.get_obj(), "complete").get_bool() == false);
123     r = CallRPC(std::string("signrawtransactionwithkey ")+notsigned+" ["+privkey1+","+privkey2+"] "+prevout);
124     BOOST_CHECK(find_value(r.get_obj(), "complete").get_bool() == true);
125     g_rpc_interfaces = nullptr;
126 }
127 
BOOST_AUTO_TEST_CASE(rpc_createraw_op_return)128 BOOST_AUTO_TEST_CASE(rpc_createraw_op_return)
129 {
130     BOOST_CHECK_NO_THROW(CallRPC("createrawtransaction [{\"txid\":\"a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff150ed\",\"vout\":0}] {\"data\":\"68656c6c6f776f726c64\"}"));
131 
132     // Key not "data" (bad address)
133     BOOST_CHECK_THROW(CallRPC("createrawtransaction [{\"txid\":\"a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff150ed\",\"vout\":0}] {\"somedata\":\"68656c6c6f776f726c64\"}"), std::runtime_error);
134 
135     // Bad hex encoding of data output
136     BOOST_CHECK_THROW(CallRPC("createrawtransaction [{\"txid\":\"a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff150ed\",\"vout\":0}] {\"data\":\"12345\"}"), std::runtime_error);
137     BOOST_CHECK_THROW(CallRPC("createrawtransaction [{\"txid\":\"a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff150ed\",\"vout\":0}] {\"data\":\"12345g\"}"), std::runtime_error);
138 
139     // Data 81 bytes long
140     BOOST_CHECK_NO_THROW(CallRPC("createrawtransaction [{\"txid\":\"a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff150ed\",\"vout\":0}] {\"data\":\"010203040506070809101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081\"}"));
141 }
142 
BOOST_AUTO_TEST_CASE(rpc_format_monetary_values)143 BOOST_AUTO_TEST_CASE(rpc_format_monetary_values)
144 {
145     BOOST_CHECK(ValueFromAmount(0LL).write() == "0.00000000");
146     BOOST_CHECK(ValueFromAmount(1LL).write() == "0.00000001");
147     BOOST_CHECK(ValueFromAmount(17622195LL).write() == "0.17622195");
148     BOOST_CHECK(ValueFromAmount(50000000LL).write() == "0.50000000");
149     BOOST_CHECK(ValueFromAmount(89898989LL).write() == "0.89898989");
150     BOOST_CHECK(ValueFromAmount(100000000LL).write() == "1.00000000");
151     BOOST_CHECK(ValueFromAmount(2099999999999990LL).write() == "20999999.99999990");
152     BOOST_CHECK(ValueFromAmount(2099999999999999LL).write() == "20999999.99999999");
153 
154     BOOST_CHECK_EQUAL(ValueFromAmount(0).write(), "0.00000000");
155     BOOST_CHECK_EQUAL(ValueFromAmount((COIN/10000)*123456789).write(), "12345.67890000");
156     BOOST_CHECK_EQUAL(ValueFromAmount(-COIN).write(), "-1.00000000");
157     BOOST_CHECK_EQUAL(ValueFromAmount(-COIN/10).write(), "-0.10000000");
158 
159     BOOST_CHECK_EQUAL(ValueFromAmount(COIN*100000000).write(), "100000000.00000000");
160     BOOST_CHECK_EQUAL(ValueFromAmount(COIN*10000000).write(), "10000000.00000000");
161     BOOST_CHECK_EQUAL(ValueFromAmount(COIN*1000000).write(), "1000000.00000000");
162     BOOST_CHECK_EQUAL(ValueFromAmount(COIN*100000).write(), "100000.00000000");
163     BOOST_CHECK_EQUAL(ValueFromAmount(COIN*10000).write(), "10000.00000000");
164     BOOST_CHECK_EQUAL(ValueFromAmount(COIN*1000).write(), "1000.00000000");
165     BOOST_CHECK_EQUAL(ValueFromAmount(COIN*100).write(), "100.00000000");
166     BOOST_CHECK_EQUAL(ValueFromAmount(COIN*10).write(), "10.00000000");
167     BOOST_CHECK_EQUAL(ValueFromAmount(COIN).write(), "1.00000000");
168     BOOST_CHECK_EQUAL(ValueFromAmount(COIN/10).write(), "0.10000000");
169     BOOST_CHECK_EQUAL(ValueFromAmount(COIN/100).write(), "0.01000000");
170     BOOST_CHECK_EQUAL(ValueFromAmount(COIN/1000).write(), "0.00100000");
171     BOOST_CHECK_EQUAL(ValueFromAmount(COIN/10000).write(), "0.00010000");
172     BOOST_CHECK_EQUAL(ValueFromAmount(COIN/100000).write(), "0.00001000");
173     BOOST_CHECK_EQUAL(ValueFromAmount(COIN/1000000).write(), "0.00000100");
174     BOOST_CHECK_EQUAL(ValueFromAmount(COIN/10000000).write(), "0.00000010");
175     BOOST_CHECK_EQUAL(ValueFromAmount(COIN/100000000).write(), "0.00000001");
176 }
177 
ValueFromString(const std::string & str)178 static UniValue ValueFromString(const std::string &str)
179 {
180     UniValue value;
181     BOOST_CHECK(value.setNumStr(str));
182     return value;
183 }
184 
BOOST_AUTO_TEST_CASE(rpc_parse_monetary_values)185 BOOST_AUTO_TEST_CASE(rpc_parse_monetary_values)
186 {
187     BOOST_CHECK_THROW(AmountFromValue(ValueFromString("-0.00000001")), UniValue);
188     BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0")), 0LL);
189     BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.00000000")), 0LL);
190     BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.00000001")), 1LL);
191     BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.17622195")), 17622195LL);
192     BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.5")), 50000000LL);
193     BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.50000000")), 50000000LL);
194     BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.89898989")), 89898989LL);
195     BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("1.00000000")), 100000000LL);
196     BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("20999999.9999999")), 2099999999999990LL);
197     BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("20999999.99999999")), 2099999999999999LL);
198 
199     BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("1e-8")), COIN/100000000);
200     BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.1e-7")), COIN/100000000);
201     BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.01e-6")), COIN/100000000);
202     BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.0000000000000000000000000000000000000000000000000000000000000000000000000001e+68")), COIN/100000000);
203     BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("10000000000000000000000000000000000000000000000000000000000000000e-64")), COIN);
204     BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000e64")), COIN);
205 
206     BOOST_CHECK_THROW(AmountFromValue(ValueFromString("1e-9")), UniValue); //should fail
207     BOOST_CHECK_THROW(AmountFromValue(ValueFromString("0.000000019")), UniValue); //should fail
208     BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.00000001000000")), 1LL); //should pass, cut trailing 0
209     BOOST_CHECK_THROW(AmountFromValue(ValueFromString("19e-9")), UniValue); //should fail
210     BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.19e-6")), 19); //should pass, leading 0 is present
211 
212     BOOST_CHECK_THROW(AmountFromValue(ValueFromString("92233720368.54775808")), UniValue); //overflow error
213     BOOST_CHECK_THROW(AmountFromValue(ValueFromString("1e+11")), UniValue); //overflow error
214     BOOST_CHECK_THROW(AmountFromValue(ValueFromString("1e11")), UniValue); //overflow error signless
215     BOOST_CHECK_THROW(AmountFromValue(ValueFromString("93e+9")), UniValue); //overflow error
216 }
217 
BOOST_AUTO_TEST_CASE(json_parse_errors)218 BOOST_AUTO_TEST_CASE(json_parse_errors)
219 {
220     // Valid
221     BOOST_CHECK_EQUAL(ParseNonRFCJSONValue("1.0").get_real(), 1.0);
222     // Valid, with leading or trailing whitespace
223     BOOST_CHECK_EQUAL(ParseNonRFCJSONValue(" 1.0").get_real(), 1.0);
224     BOOST_CHECK_EQUAL(ParseNonRFCJSONValue("1.0 ").get_real(), 1.0);
225 
226     BOOST_CHECK_THROW(AmountFromValue(ParseNonRFCJSONValue(".19e-6")), std::runtime_error); //should fail, missing leading 0, therefore invalid JSON
227     BOOST_CHECK_EQUAL(AmountFromValue(ParseNonRFCJSONValue("0.00000000000000000000000000000000000001e+30 ")), 1);
228     // Invalid, initial garbage
229     BOOST_CHECK_THROW(ParseNonRFCJSONValue("[1.0"), std::runtime_error);
230     BOOST_CHECK_THROW(ParseNonRFCJSONValue("a1.0"), std::runtime_error);
231     // Invalid, trailing garbage
232     BOOST_CHECK_THROW(ParseNonRFCJSONValue("1.0sds"), std::runtime_error);
233     BOOST_CHECK_THROW(ParseNonRFCJSONValue("1.0]"), std::runtime_error);
234     // BTC addresses should fail parsing
235     BOOST_CHECK_THROW(ParseNonRFCJSONValue("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"), std::runtime_error);
236     BOOST_CHECK_THROW(ParseNonRFCJSONValue("3J98t1WpEZ73CNmQviecrnyiWrnqRhWNL"), std::runtime_error);
237 }
238 
BOOST_AUTO_TEST_CASE(rpc_ban)239 BOOST_AUTO_TEST_CASE(rpc_ban)
240 {
241     BOOST_CHECK_NO_THROW(CallRPC(std::string("clearbanned")));
242 
243     UniValue r;
244     BOOST_CHECK_NO_THROW(r = CallRPC(std::string("setban 127.0.0.0 add")));
245     BOOST_CHECK_THROW(r = CallRPC(std::string("setban 127.0.0.0:8334")), std::runtime_error); //portnumber for setban not allowed
246     BOOST_CHECK_NO_THROW(r = CallRPC(std::string("listbanned")));
247     UniValue ar = r.get_array();
248     UniValue o1 = ar[0].get_obj();
249     UniValue adr = find_value(o1, "address");
250     BOOST_CHECK_EQUAL(adr.get_str(), "127.0.0.0/32");
251     BOOST_CHECK_NO_THROW(CallRPC(std::string("setban 127.0.0.0 remove")));
252     BOOST_CHECK_NO_THROW(r = CallRPC(std::string("listbanned")));
253     ar = r.get_array();
254     BOOST_CHECK_EQUAL(ar.size(), 0U);
255 
256     BOOST_CHECK_NO_THROW(r = CallRPC(std::string("setban 127.0.0.0/24 add 9907731200 true")));
257     BOOST_CHECK_NO_THROW(r = CallRPC(std::string("listbanned")));
258     ar = r.get_array();
259     o1 = ar[0].get_obj();
260     adr = find_value(o1, "address");
261     UniValue banned_until = find_value(o1, "banned_until");
262     BOOST_CHECK_EQUAL(adr.get_str(), "127.0.0.0/24");
263     BOOST_CHECK_EQUAL(banned_until.get_int64(), 9907731200); // absolute time check
264 
265     BOOST_CHECK_NO_THROW(CallRPC(std::string("clearbanned")));
266 
267     BOOST_CHECK_NO_THROW(r = CallRPC(std::string("setban 127.0.0.0/24 add 200")));
268     BOOST_CHECK_NO_THROW(r = CallRPC(std::string("listbanned")));
269     ar = r.get_array();
270     o1 = ar[0].get_obj();
271     adr = find_value(o1, "address");
272     banned_until = find_value(o1, "banned_until");
273     BOOST_CHECK_EQUAL(adr.get_str(), "127.0.0.0/24");
274     int64_t now = GetTime();
275     BOOST_CHECK(banned_until.get_int64() > now);
276     BOOST_CHECK(banned_until.get_int64()-now <= 200);
277 
278     // must throw an exception because 127.0.0.1 is in already banned subnet range
279     BOOST_CHECK_THROW(r = CallRPC(std::string("setban 127.0.0.1 add")), std::runtime_error);
280 
281     BOOST_CHECK_NO_THROW(CallRPC(std::string("setban 127.0.0.0/24 remove")));
282     BOOST_CHECK_NO_THROW(r = CallRPC(std::string("listbanned")));
283     ar = r.get_array();
284     BOOST_CHECK_EQUAL(ar.size(), 0U);
285 
286     BOOST_CHECK_NO_THROW(r = CallRPC(std::string("setban 127.0.0.0/255.255.0.0 add")));
287     BOOST_CHECK_THROW(r = CallRPC(std::string("setban 127.0.1.1 add")), std::runtime_error);
288 
289     BOOST_CHECK_NO_THROW(CallRPC(std::string("clearbanned")));
290     BOOST_CHECK_NO_THROW(r = CallRPC(std::string("listbanned")));
291     ar = r.get_array();
292     BOOST_CHECK_EQUAL(ar.size(), 0U);
293 
294 
295     BOOST_CHECK_THROW(r = CallRPC(std::string("setban test add")), std::runtime_error); //invalid IP
296 
297     //IPv6 tests
298     BOOST_CHECK_NO_THROW(r = CallRPC(std::string("setban FE80:0000:0000:0000:0202:B3FF:FE1E:8329 add")));
299     BOOST_CHECK_NO_THROW(r = CallRPC(std::string("listbanned")));
300     ar = r.get_array();
301     o1 = ar[0].get_obj();
302     adr = find_value(o1, "address");
303     BOOST_CHECK_EQUAL(adr.get_str(), "fe80::202:b3ff:fe1e:8329/128");
304 
305     BOOST_CHECK_NO_THROW(CallRPC(std::string("clearbanned")));
306     BOOST_CHECK_NO_THROW(r = CallRPC(std::string("setban 2001:db8::/ffff:fffc:0:0:0:0:0:0 add")));
307     BOOST_CHECK_NO_THROW(r = CallRPC(std::string("listbanned")));
308     ar = r.get_array();
309     o1 = ar[0].get_obj();
310     adr = find_value(o1, "address");
311     BOOST_CHECK_EQUAL(adr.get_str(), "2001:db8::/30");
312 
313     BOOST_CHECK_NO_THROW(CallRPC(std::string("clearbanned")));
314     BOOST_CHECK_NO_THROW(r = CallRPC(std::string("setban 2001:4d48:ac57:400:cacf:e9ff:fe1d:9c63/128 add")));
315     BOOST_CHECK_NO_THROW(r = CallRPC(std::string("listbanned")));
316     ar = r.get_array();
317     o1 = ar[0].get_obj();
318     adr = find_value(o1, "address");
319     BOOST_CHECK_EQUAL(adr.get_str(), "2001:4d48:ac57:400:cacf:e9ff:fe1d:9c63/128");
320 }
321 
BOOST_AUTO_TEST_CASE(rpc_convert_values_generatetoaddress)322 BOOST_AUTO_TEST_CASE(rpc_convert_values_generatetoaddress)
323 {
324     UniValue result;
325 
326     BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", {"101", "mkESjLZW66TmHhiFX8MCaBjrhZ543PPh9a"}));
327     BOOST_CHECK_EQUAL(result[0].get_int(), 101);
328     BOOST_CHECK_EQUAL(result[1].get_str(), "mkESjLZW66TmHhiFX8MCaBjrhZ543PPh9a");
329 
330     BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", {"101", "mhMbmE2tE9xzJYCV9aNC8jKWN31vtGrguU"}));
331     BOOST_CHECK_EQUAL(result[0].get_int(), 101);
332     BOOST_CHECK_EQUAL(result[1].get_str(), "mhMbmE2tE9xzJYCV9aNC8jKWN31vtGrguU");
333 
334     BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", {"1", "mkESjLZW66TmHhiFX8MCaBjrhZ543PPh9a", "9"}));
335     BOOST_CHECK_EQUAL(result[0].get_int(), 1);
336     BOOST_CHECK_EQUAL(result[1].get_str(), "mkESjLZW66TmHhiFX8MCaBjrhZ543PPh9a");
337     BOOST_CHECK_EQUAL(result[2].get_int(), 9);
338 
339     BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", {"1", "mhMbmE2tE9xzJYCV9aNC8jKWN31vtGrguU", "9"}));
340     BOOST_CHECK_EQUAL(result[0].get_int(), 1);
341     BOOST_CHECK_EQUAL(result[1].get_str(), "mhMbmE2tE9xzJYCV9aNC8jKWN31vtGrguU");
342     BOOST_CHECK_EQUAL(result[2].get_int(), 9);
343 }
344 
BOOST_AUTO_TEST_CASE(rpc_getblockstats_calculate_percentiles_by_weight)345 BOOST_AUTO_TEST_CASE(rpc_getblockstats_calculate_percentiles_by_weight)
346 {
347     int64_t total_weight = 200;
348     std::vector<std::pair<CAmount, int64_t>> feerates;
349     CAmount result[NUM_GETBLOCKSTATS_PERCENTILES] = { 0 };
350 
351     for (int64_t i = 0; i < 100; i++) {
352         feerates.emplace_back(std::make_pair(1 ,1));
353     }
354 
355     for (int64_t i = 0; i < 100; i++) {
356         feerates.emplace_back(std::make_pair(2 ,1));
357     }
358 
359     CalculatePercentilesByWeight(result, feerates, total_weight);
360     BOOST_CHECK_EQUAL(result[0], 1);
361     BOOST_CHECK_EQUAL(result[1], 1);
362     BOOST_CHECK_EQUAL(result[2], 1);
363     BOOST_CHECK_EQUAL(result[3], 2);
364     BOOST_CHECK_EQUAL(result[4], 2);
365 
366     // Test with more pairs, and two pairs overlapping 2 percentiles.
367     total_weight = 100;
368     CAmount result2[NUM_GETBLOCKSTATS_PERCENTILES] = { 0 };
369     feerates.clear();
370 
371     feerates.emplace_back(std::make_pair(1, 9));
372     feerates.emplace_back(std::make_pair(2 , 16)); //10th + 25th percentile
373     feerates.emplace_back(std::make_pair(4 ,50)); //50th + 75th percentile
374     feerates.emplace_back(std::make_pair(5 ,10));
375     feerates.emplace_back(std::make_pair(9 ,15));  // 90th percentile
376 
377     CalculatePercentilesByWeight(result2, feerates, total_weight);
378 
379     BOOST_CHECK_EQUAL(result2[0], 2);
380     BOOST_CHECK_EQUAL(result2[1], 2);
381     BOOST_CHECK_EQUAL(result2[2], 4);
382     BOOST_CHECK_EQUAL(result2[3], 4);
383     BOOST_CHECK_EQUAL(result2[4], 9);
384 
385     // Same test as above, but one of the percentile-overlapping pairs is split in 2.
386     total_weight = 100;
387     CAmount result3[NUM_GETBLOCKSTATS_PERCENTILES] = { 0 };
388     feerates.clear();
389 
390     feerates.emplace_back(std::make_pair(1, 9));
391     feerates.emplace_back(std::make_pair(2 , 11)); // 10th percentile
392     feerates.emplace_back(std::make_pair(2 , 5)); // 25th percentile
393     feerates.emplace_back(std::make_pair(4 ,50)); //50th + 75th percentile
394     feerates.emplace_back(std::make_pair(5 ,10));
395     feerates.emplace_back(std::make_pair(9 ,15)); // 90th percentile
396 
397     CalculatePercentilesByWeight(result3, feerates, total_weight);
398 
399     BOOST_CHECK_EQUAL(result3[0], 2);
400     BOOST_CHECK_EQUAL(result3[1], 2);
401     BOOST_CHECK_EQUAL(result3[2], 4);
402     BOOST_CHECK_EQUAL(result3[3], 4);
403     BOOST_CHECK_EQUAL(result3[4], 9);
404 
405     // Test with one transaction spanning all percentiles.
406     total_weight = 104;
407     CAmount result4[NUM_GETBLOCKSTATS_PERCENTILES] = { 0 };
408     feerates.clear();
409 
410     feerates.emplace_back(std::make_pair(1, 100));
411     feerates.emplace_back(std::make_pair(2, 1));
412     feerates.emplace_back(std::make_pair(3, 1));
413     feerates.emplace_back(std::make_pair(3, 1));
414     feerates.emplace_back(std::make_pair(999999, 1));
415 
416     CalculatePercentilesByWeight(result4, feerates, total_weight);
417 
418     for (int64_t i = 0; i < NUM_GETBLOCKSTATS_PERCENTILES; i++) {
419         BOOST_CHECK_EQUAL(result4[i], 1);
420     }
421 }
422 
423 BOOST_AUTO_TEST_SUITE_END()
424