20 #include <ripple/basics/contract.h>
21 #include <ripple/core/Config.h>
22 #include <ripple/core/ConfigSections.h>
23 #include <ripple/server/Port.h>
24 #include <boost/filesystem.hpp>
25 #include <boost/format.hpp>
28 #include <test/jtx/TestSuite.h>
29 #include <test/unit_test/FileDirGuard.h>
36 static boost::format configContentsTemplate(R
"rippleConfig(
45 admin = 127.0.0.1, ::1
64 #-------------------------------------------------------------------------------
69 # This is primary persistent datastore for rippled. This includes transaction
70 # metadata, account states, and ledger headers. Helpful information can be
71 # found on https://xrpl.org/capacity-planning.html#node-db-type
72 # delete old ledgers while maintaining at least 2000. Do not require an
73 # external administrative command to initiate deletion.
76 path=/Users/dummy/ripple/config/db/rocksdb
87 # This needs to be an absolute directory reference, not a relative one.
88 # Modify this value as required.
90 /Users/dummy/ripple/config/log/debug.log
98 # Where to find some other servers speaking the Ripple protocol.
103 # Turn down default logging to save disk space in the long run.
104 # Valid values here are trace, debug, info, warning, error, and fatal
106 { "command": "log_level", "severity": "warning" }
108 # Defaults to 1 ("yes") so that certificates will be validated. To allow the use
109 # of self-signed certificates for development or internal use, set to 0 ("no").
118 dbPath.empty() ? "" :
"[database_path]\n" + dbPath;
120 validatorsFile.
empty() ?
"" :
"[validators_file]\n" + validatorsFile;
121 return boost::str(configContentsTemplate % dbPathSection % valFileSection);
138 beast::unit_test::suite& test,
141 path const& validatorsFile,
142 bool useCounter =
true)
171 return file().string();
177 return boost::filesystem::is_directory(
dataDir_);
190 using namespace boost::filesystem;
207 n949f75evCHwgyP4fPVgaHqNHxUVN15PsJEZ3B3HnXPcPjcZAoy7
208 n9MD5h24qrQqiyBC8aeqqCWvpiBiYQ3jxSr91uiDvmrkyHRdYLUj
209 n9L81uNCaPgtUJfaHh89gmdvXKAmSt5Gdsw2g1iPWaPkAHW5Nm4C
210 n9KiYM9CgngLvtRCQHZwgC2gjpdaZcCcbt3VboxiNFcKuwFVujzS
211 n9LdgEtkmGB9E2h3K4Vp7iGUaKuq23Zr32ehxiU8FWY7xoxbWTSA
214 nHUhG1PgAG8H8myUENypM35JgfqXAKNQvRVVAFDRzJrny5eZN8d5
215 nHBu9PTL9dn2GuZtdW4U2WzBwffyX9qsQCd9CNU4Z5YG3PQfViM8
216 nHUPDdcdb2Y5DZAJne4c2iabFuAP3F34xZUgYQT2NH7qfkdapgnz
218 [validator_list_sites]
219 recommendedripplevalidators.com
220 moreripplevalidators.net
222 [validator_list_keys]
223 03E74EE14CB525AFBB9F1B7D86CD58ECC4B91452294B42AB4E78F260BD905C091D
224 030775A669685BD6ABCEBD80385921C7851783D991A8055FD21D2F3966C96F1B56
236 beast::unit_test::suite& test,
238 path const& validatorsFileName,
239 bool useCounter =
true)
244 validatorsFileName.empty() ?
Config::validatorsFileName
245 : validatorsFileName),
260 return absolute(
file()).string();
272 using path = boost::filesystem::path;
294 BEAST_EXPECT(c.legacy("ssl_verify") ==
"0");
295 expectException([&c] { c.
legacy(
"server"); });
298 BEAST_EXPECT(c.
legacy(
"not_in_file") ==
"");
299 c.
legacy(
"not_in_file",
"new_value");
300 BEAST_EXPECT(c.
legacy(
"not_in_file") ==
"new_value");
305 testcase(
"database_path");
307 using namespace boost::filesystem;
309 boost::format cc(
"[database_path]\n%1%\n");
311 auto const cwd = current_path();
312 path const dataDirRel(
"test_data_dir");
313 path const dataDirAbs(cwd / dataDirRel);
318 BEAST_EXPECT(c.
legacy(
"database_path") == dataDirAbs.string());
324 BEAST_EXPECT(c.
legacy(
"database_path") == dataDirAbs.string());
332 BEAST_EXPECT(c.
legacy(
"database_path") ==
"");
337 auto const cwd = current_path();
339 path const dataDirRel(
"test_data_dir");
340 path const dataDirAbs(cwd / g0.
subdir() / dataDirRel);
342 *
this, g0.
subdir(), dataDirAbs,
"",
false);
343 auto const& c(g.
config());
346 BEAST_EXPECT(c.legacy(
"database_path") == dataDirAbs.string());
352 auto const& c(g.
config());
356 BEAST_EXPECT(c.legacy(
"database_path") == nativeDbPath);
361 auto const& c(g.
config());
366 BEAST_EXPECT(c.legacy(
"database_path") == nativeDbPath);
373 testcase(
"validator keys");
378 "eyJ2YWxpZGF0aW9uX3ByaXZhdGVfa2V5IjoiOWVkNDVmODY2MjQxY2MxOGEyNzQ3Yj"
379 "U0Mzg3YzA2MjU5MDc5NzJmNGU3MTkwMjMxZmFhOTM3NDU3ZmE5ZGFmNiIsIm1hbmlm"
380 "ZXN0IjoiSkFBQUFBRnhJZTFGdHdtaW12R3RIMmlDY01KcUM5Z1ZGS2lsR2Z3MS92Q3"
381 "hIWFhMcGxjMkduTWhBa0UxYWdxWHhCd0R3RGJJRDZPTVNZdU0wRkRBbHBBZ05rOFNL"
382 "Rm43TU8yZmRrY3dSUUloQU9uZ3U5c0FLcVhZb3VKK2wyVjBXK3NBT2tWQitaUlM2UF"
383 "NobEpBZlVzWGZBaUJzVkpHZXNhYWRPSmMvYUFab2tTMXZ5bUdtVnJsSFBLV1gzWXl3"
384 "dTZpbjhIQVNRS1B1Z0JENjdrTWFSRkd2bXBBVEhsR0tKZHZERmxXUFl5NUFxRGVkRn"
385 "Y1VEphMncwaTIxZXEzTVl5d0xWSlpuRk9yN0Mwa3cyQWlUelNDakl6ZGl0UTg9In0"
390 static boost::format configTemplate(R
"rippleConfig(
398 auto const expectedError =
399 "Cannot have both [validation_seed] "
400 "and [validator_token] config sections";
410 BEAST_EXPECT(error == expectedError);
417 testcase(
"validators_file");
419 using namespace boost::filesystem;
422 boost::format cc(
"[validators_file]\n%1%\n");
424 std::string const missingPath =
"/no/way/this/path/exists";
425 auto const expectedError =
426 "The file specified in [validators_file] does not exist: " +
437 BEAST_EXPECT(error == expectedError);
442 *
this,
"test_cfg",
"validators.cfg");
443 path const invalidFile = current_path() / vtg.
subdir();
444 boost::format cc(
"[validators_file]\n%1%\n");
446 auto const expectedError =
447 "Invalid file specified in [validators_file]: " +
448 invalidFile.string();
458 BEAST_EXPECT(error == expectedError);
465 n949f75evCHwgyP4fPVgaHqNHxUVN15PsJEZ3B3HnXPcPjcZAoy7
466 n9MD5h24qrQqiyBC8aeqqCWvpiBiYQ3jxSr91uiDvmrkyHRdYLUj
467 n9L81uNCaPgtUJfaHh89gmdvXKAmSt5Gdsw2g1iPWaPkAHW5Nm4C
470 nHUhG1PgAG8H8myUENypM35JgfqXAKNQvRVVAFDRzJrny5eZN8d5
471 nHBu9PTL9dn2GuZtdW4U2WzBwffyX9qsQCd9CNU4Z5YG3PQfViM8
474 BEAST_EXPECT(c.legacy("validators_file").empty());
481 [validator_list_sites]
483 trustthesevalidators.gov
485 [validator_list_keys]
486 021A99A537FDEBC34E4FCA03B39BEADD04299BB19E85097EC92B15A3518801E566
493 "ripplevalidators.com");
496 "trustthesevalidators.gov");
501 "021A99A537FDEBC34E4FCA03B39BEADD04299BB19E85097EC92B15A3518801"
509 [validator_list_sites]
511 trustthesevalidators.gov
514 auto const expectedError =
515 "[validator_list_keys] config section is missing";
524 BEAST_EXPECT(error == expectedError);
529 *
this,
"test_cfg",
"validators.cfg");
532 boost::format cc(
"[validators_file]\n%1%\n");
546 *
this,
"test_cfg", valFileName);
548 *
this, vtg.
subdir(),
"", valFileName,
false);
551 auto const& c(rcg.
config());
552 BEAST_EXPECT(c.legacy(
"validators_file") == valFileName);
553 BEAST_EXPECT(c.section(SECTION_VALIDATORS).values().size() == 8);
555 c.section(SECTION_VALIDATOR_LIST_SITES).values().size() == 2);
557 c.section(SECTION_VALIDATOR_LIST_KEYS).values().size() == 2);
563 *
this,
"test_cfg",
"validators.txt");
564 auto const valFilePath =
".." / vtg.
subdir() /
"validators.txt";
566 *
this, vtg.
subdir(),
"", valFilePath,
false);
569 auto const& c(rcg.
config());
570 BEAST_EXPECT(c.legacy(
"validators_file") == valFilePath);
571 BEAST_EXPECT(c.section(SECTION_VALIDATORS).values().size() == 8);
573 c.section(SECTION_VALIDATOR_LIST_SITES).values().size() == 2);
575 c.section(SECTION_VALIDATOR_LIST_KEYS).values().size() == 2);
580 *
this,
"test_cfg",
"validators.txt");
582 *
this, vtg.
subdir(),
"",
"",
false);
585 auto const& c(rcg.
config());
586 BEAST_EXPECT(c.legacy(
"validators_file").empty());
587 BEAST_EXPECT(c.section(SECTION_VALIDATORS).values().size() == 8);
589 c.section(SECTION_VALIDATOR_LIST_SITES).values().size() == 2);
591 c.section(SECTION_VALIDATOR_LIST_KEYS).values().size() == 2);
597 *
this,
"test_cfg",
"validators.cfg");
600 *
this, vtg.
subdir(),
"validators.txt",
false);
605 auto const& c(rcg.
config());
606 BEAST_EXPECT(c.legacy(
"validators_file") == vtg.
validatorsFile());
607 BEAST_EXPECT(c.section(SECTION_VALIDATORS).values().size() == 8);
609 c.section(SECTION_VALIDATOR_LIST_SITES).values().size() == 2);
611 c.section(SECTION_VALIDATOR_LIST_KEYS).values().size() == 2);
616 boost::format cc(R
"rippleConfig(
621 n949f75evCHwgyP4fPVgaHqNHxUVN15PsJEZ3B3HnXPcPjcZAoy7
622 n9MD5h24qrQqiyBC8aeqqCWvpiBiYQ3jxSr91uiDvmrkyHRdYLUj
623 n9L81uNCaPgtUJfaHh89gmdvXKAmSt5Gdsw2g1iPWaPkAHW5Nm4C
624 n9KiYM9CgngLvtRCQHZwgC2gjpdaZcCcbt3VboxiNFcKuwFVujzS
625 n9LdgEtkmGB9E2h3K4Vp7iGUaKuq23Zr32ehxiU8FWY7xoxbWTSA
628 nHB1X37qrniVugfQcuBTAjswphC1drx7QjFFojJPZwKHHnt8kU7v
629 nHUkAWDR4cB8AgPg7VXMX6et8xRTQb2KJfgv1aBEXozwrawRKgMB
631 [validator_list_sites]
633 trustthesevalidators.gov
635 [validator_list_keys]
636 021A99A537FDEBC34E4FCA03B39BEADD04299BB19E85097EC92B15A3518801E566
639 *
this,
"test_cfg",
"validators.cfg");
655 boost::format cc(
"[validators_file]\n%1%\n");
658 *
this,
"test_cfg",
"validators.cfg");
660 auto const expectedError =
661 "The file specified in [validators_file] does not contain a "
662 "[validators], [validator_keys] or [validator_list_keys] "
675 BEAST_EXPECT(error == expectedError);
683 *
this,
"testSetup", explicitPath ?
"test_db" :
"",
"");
695 BEAST_EXPECT(!config.
quiet());
696 BEAST_EXPECT(!config.
silent());
699 BEAST_EXPECT(!config.
legacy(
"database_path").empty());
708 BEAST_EXPECT(config.
quiet());
709 BEAST_EXPECT(!config.
silent());
712 BEAST_EXPECT(!config.
legacy(
"database_path").empty());
721 BEAST_EXPECT(config.
quiet());
722 BEAST_EXPECT(config.
silent());
725 BEAST_EXPECT(!config.
legacy(
"database_path").empty());
734 BEAST_EXPECT(config.
quiet());
735 BEAST_EXPECT(config.
silent());
738 BEAST_EXPECT(!config.
legacy(
"database_path").empty());
747 BEAST_EXPECT(!config.
quiet());
748 BEAST_EXPECT(!config.
silent());
752 config.
legacy(
"database_path").empty() == !explicitPath);
761 BEAST_EXPECT(config.
quiet());
762 BEAST_EXPECT(!config.
silent());
766 config.
legacy(
"database_path").empty() == !explicitPath);
775 BEAST_EXPECT(config.
quiet());
776 BEAST_EXPECT(config.
silent());
780 config.
legacy(
"database_path").empty() == !explicitPath);
789 BEAST_EXPECT(config.
quiet());
790 BEAST_EXPECT(config.
silent());
794 config.
legacy(
"database_path").empty() == !explicitPath);
802 auto const& conf = cfg.
config();
803 if (!BEAST_EXPECT(conf.exists(
"port_rpc")))
805 if (!BEAST_EXPECT(conf.exists(
"port_wss_admin")))
808 if (!unexcept([&]() {
parse_Port(rpc, conf[
"port_rpc"], log); }))
812 if (!unexcept([&]() {
parse_Port(wss, conf[
"port_wss_admin"], log); }))
850 cfg.exists(SECTION_IPS) &&
851 cfg.section(SECTION_IPS).lines().size() == 1 &&
852 cfg.section(SECTION_IPS).values().size() == 1);
854 cfg.exists(SECTION_IPS_FIXED) &&
855 cfg.section(SECTION_IPS_FIXED).lines().size() == 2 &&
856 cfg.section(SECTION_IPS_FIXED).values().size() == 2);
885 anotherserversansport
886 anotherserverwithport:12
896 2001:db8:3333:4444:5555:6666:7777:8888:12345
897 [2001:db8:3333:4444:5555:6666:7777:8888]:1
906 cfg.
exists(SECTION_IPS) &&
910 cfg.
exists(SECTION_IPS_FIXED) &&
913 BEAST_EXPECT(cfg.
IPS[0] ==
"r.ripple.com 51235");
915 BEAST_EXPECT(cfg.
IPS_FIXED[0] ==
"s1.ripple.com 51235");
916 BEAST_EXPECT(cfg.
IPS_FIXED[1] ==
"s2.ripple.com 51235");
917 BEAST_EXPECT(cfg.
IPS_FIXED[2] ==
"anotherserversansport");
918 BEAST_EXPECT(cfg.
IPS_FIXED[3] ==
"anotherserverwithport 12");
919 BEAST_EXPECT(cfg.
IPS_FIXED[4] ==
"1.1.1.1 1");
920 BEAST_EXPECT(cfg.
IPS_FIXED[5] ==
"1.1.1.1 1");
921 BEAST_EXPECT(cfg.
IPS_FIXED[6] ==
"12.34.12.123 12345");
922 BEAST_EXPECT(cfg.
IPS_FIXED[7] ==
"12.34.12.123 12345");
926 BEAST_EXPECT(cfg.
IPS_FIXED[9] ==
"2001:db8::");
927 BEAST_EXPECT(cfg.
IPS_FIXED[10] ==
"::1");
928 BEAST_EXPECT(cfg.
IPS_FIXED[11] ==
"::1:12345");
929 BEAST_EXPECT(cfg.
IPS_FIXED[12] ==
"[::1]:12345");
932 "2001:db8:3333:4444:5555:6666:7777:8888:12345");
934 cfg.
IPS_FIXED[14] ==
"[2001:db8:3333:4444:5555:6666:7777:8888]:1");
940 struct TestCommentData
949 {{
"password = aaaa\\#bbbb",
"password",
"aaaa#bbbb",
false},
950 {
"password = aaaa#bbbb",
"password",
"aaaa",
true},
951 {
"password = aaaa #bbbb",
"password",
"aaaa",
true},
953 {
"password = #aaaa #bbbb",
"",
"password =",
true},
954 {
"password = aaaa\\# #bbbb",
"password",
"aaaa#",
true},
955 {
"password = aaaa\\##bbbb",
"password",
"aaaa#",
true},
956 {
"aaaa#bbbb",
"",
"aaaa",
true},
957 {
"aaaa\\#bbbb",
"",
"aaaa#bbbb",
false},
958 {
"aaaa\\##bbbb",
"",
"aaaa#",
true},
959 {
"aaaa #bbbb",
"",
"aaaa",
true},
960 {
"1 #comment",
"",
"1",
true},
961 {
"#whole thing is comment",
"",
"",
false},
962 {
" #whole comment with space",
"",
"",
false}}};
964 for (
auto const& t : tests)
967 s.append(t.line.data());
968 BEAST_EXPECT(s.had_trailing_comments() == t.had_comment);
971 BEAST_EXPECTS(s.legacy() == t.expect, s.legacy());
976 BEAST_EXPECTS(
set(field, t.field.data(), s), t.line);
977 BEAST_EXPECTS(field == t.expect, t.line);
983 s.append(
"online_delete = 3000");
985 BEAST_EXPECT(
set(od,
"online_delete", s));
986 BEAST_EXPECTS(od == 3000, *(s.get<
std::string>(
"online_delete")));
991 s.append(
"online_delete = 2000 #my comment on this");
993 BEAST_EXPECT(
set(od,
"online_delete", s));
994 BEAST_EXPECTS(od == 2000, *(s.get<
std::string>(
"online_delete")));
1001 using namespace std::string_literals;
1002 Section s{
"MySection"};
1003 s.append(
"a_string = mystring");
1004 s.append(
"positive_int = 2");
1005 s.append(
"negative_int = -3");
1006 s.append(
"bool_ish = 1");
1009 auto val_1 =
"value 1"s;
1010 BEAST_EXPECT(
set(val_1,
"a_string", s));
1011 BEAST_EXPECT(val_1 ==
"mystring");
1013 auto val_2 =
"value 2"s;
1014 BEAST_EXPECT(!
set(val_2,
"not_a_key", s));
1015 BEAST_EXPECT(val_2 ==
"value 2");
1016 BEAST_EXPECT(!
set(val_2,
"default"s,
"not_a_key", s));
1017 BEAST_EXPECT(val_2 ==
"default");
1019 auto val_3 = get<std::string>(s,
"a_string");
1020 BEAST_EXPECT(val_3 ==
"mystring");
1021 auto val_4 = get<std::string>(s,
"not_a_key");
1022 BEAST_EXPECT(val_4 ==
"");
1023 auto val_5 = get<std::string>(s,
"not_a_key",
"default");
1024 BEAST_EXPECT(val_5 ==
"default");
1026 auto val_6 =
"value 6"s;
1028 BEAST_EXPECT(val_6 ==
"mystring");
1030 auto val_7 =
"value 7"s;
1032 BEAST_EXPECT(val_7 ==
"value 7");
1037 BEAST_EXPECT(
set(val_1,
"positive_int", s));
1038 BEAST_EXPECT(val_1 == 2);
1041 BEAST_EXPECT(
set(val_2,
"negative_int", s));
1042 BEAST_EXPECT(val_2 == -3);
1045 BEAST_EXPECT(!
set(val_3,
"a_string", s));
1046 BEAST_EXPECT(val_3 == 3);
1048 auto val_4 = get<int>(s,
"positive_int");
1049 BEAST_EXPECT(val_4 == 2);
1050 auto val_5 = get<int>(s,
"not_a_key");
1051 BEAST_EXPECT(val_5 == 0);
1052 auto val_6 = get<int>(s,
"not_a_key", 5);
1053 BEAST_EXPECT(val_6 == 5);
1054 auto val_7 = get<int>(s,
"a_string", 6);
1055 BEAST_EXPECT(val_7 == 6);
1059 BEAST_EXPECT(val_8 == 2);
1063 BEAST_EXPECT(val_9 == 9);
1067 BEAST_EXPECT(val_10 == 10);
1069 BEAST_EXPECT(s.get<
int>(
"not_a_key") == std::nullopt);
1072 s.get<
int>(
"a_string");
1075 catch (boost::bad_lexical_cast&)
1082 bool flag_1 =
false;
1084 BEAST_EXPECT(flag_1 ==
true);
1086 bool flag_2 =
false;
1088 BEAST_EXPECT(flag_2 ==
false);
1095 testcase(
"amendment");
1105 {
"seconds", 1, 15 * 60,
false},
1106 {
"minutes", 60, 14,
false},
1107 {
"minutes", 60, 15,
true},
1108 {
"hours", 3600, 10,
true},
1109 {
"days", 86400, 10,
true},
1110 {
"weeks", 604800, 2,
true},
1111 {
"months", 2592000, 1,
false},
1112 {
"years", 31536000, 1,
false}};
1115 for (
auto& [unit, sec, val, shouldPass] : units)
1119 [amendment_majority_time]
1126 c.loadFromString(toLoad);
1129 c.AMENDMENT_MAJORITY_TIME.count() == val * sec);
1146 testcase(
"overlay: unknown time");
1153 c.loadFromString(
"[overlay]\nmax_unknown_time=" + value);
1154 return c.MAX_UNKNOWN_TIME;
1163 BEAST_EXPECT(!testUnknown(
"none"));
1164 BEAST_EXPECT(!testUnknown(
"0.5"));
1165 BEAST_EXPECT(!testUnknown(
"180 seconds"));
1166 BEAST_EXPECT(!testUnknown(
"9 minutes"));
1169 BEAST_EXPECT(!testUnknown(
"299"));
1178 BEAST_EXPECT(!testUnknown(
"1801"));
1180 testcase(
"overlay: diverged time");
1198 BEAST_EXPECT(!testDiverged(
"none"));
1199 BEAST_EXPECT(!testDiverged(
"0.5"));
1200 BEAST_EXPECT(!testDiverged(
"180 seconds"));
1201 BEAST_EXPECT(!testDiverged(
"9 minutes"));
1204 BEAST_EXPECT(!testDiverged(
"0"));
1205 BEAST_EXPECT(!testDiverged(
"59"));
1214 BEAST_EXPECT(!testDiverged(
"901"));
1222 testValidatorKeys();
1223 testValidatorsFile();