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(
"network id");
432 BEAST_EXPECT(error ==
"");
445 BEAST_EXPECT(error ==
"");
460 BEAST_EXPECT(error ==
"");
475 BEAST_EXPECT(error ==
"");
482 testcase(
"validators_file");
484 using namespace boost::filesystem;
487 boost::format cc(
"[validators_file]\n%1%\n");
489 std::string const missingPath =
"/no/way/this/path/exists";
490 auto const expectedError =
491 "The file specified in [validators_file] does not exist: " +
502 BEAST_EXPECT(error == expectedError);
507 *
this,
"test_cfg",
"validators.cfg");
508 path const invalidFile = current_path() / vtg.
subdir();
509 boost::format cc(
"[validators_file]\n%1%\n");
511 auto const expectedError =
512 "Invalid file specified in [validators_file]: " +
513 invalidFile.string();
523 BEAST_EXPECT(error == expectedError);
530 n949f75evCHwgyP4fPVgaHqNHxUVN15PsJEZ3B3HnXPcPjcZAoy7
531 n9MD5h24qrQqiyBC8aeqqCWvpiBiYQ3jxSr91uiDvmrkyHRdYLUj
532 n9L81uNCaPgtUJfaHh89gmdvXKAmSt5Gdsw2g1iPWaPkAHW5Nm4C
535 nHUhG1PgAG8H8myUENypM35JgfqXAKNQvRVVAFDRzJrny5eZN8d5
536 nHBu9PTL9dn2GuZtdW4U2WzBwffyX9qsQCd9CNU4Z5YG3PQfViM8
539 BEAST_EXPECT(c.legacy("validators_file").empty());
546 [validator_list_sites]
548 trustthesevalidators.gov
550 [validator_list_keys]
551 021A99A537FDEBC34E4FCA03B39BEADD04299BB19E85097EC92B15A3518801E566
558 "ripplevalidators.com");
561 "trustthesevalidators.gov");
566 "021A99A537FDEBC34E4FCA03B39BEADD04299BB19E85097EC92B15A3518801"
574 [validator_list_sites]
576 trustthesevalidators.gov
579 auto const expectedError =
580 "[validator_list_keys] config section is missing";
589 BEAST_EXPECT(error == expectedError);
594 *
this,
"test_cfg",
"validators.cfg");
597 boost::format cc(
"[validators_file]\n%1%\n");
611 *
this,
"test_cfg", valFileName);
613 *
this, vtg.
subdir(),
"", valFileName,
false);
616 auto const& c(rcg.
config());
617 BEAST_EXPECT(c.legacy(
"validators_file") == valFileName);
618 BEAST_EXPECT(c.section(SECTION_VALIDATORS).values().size() == 8);
620 c.section(SECTION_VALIDATOR_LIST_SITES).values().size() == 2);
622 c.section(SECTION_VALIDATOR_LIST_KEYS).values().size() == 2);
628 *
this,
"test_cfg",
"validators.txt");
629 auto const valFilePath =
".." / vtg.
subdir() /
"validators.txt";
631 *
this, vtg.
subdir(),
"", valFilePath,
false);
634 auto const& c(rcg.
config());
635 BEAST_EXPECT(c.legacy(
"validators_file") == valFilePath);
636 BEAST_EXPECT(c.section(SECTION_VALIDATORS).values().size() == 8);
638 c.section(SECTION_VALIDATOR_LIST_SITES).values().size() == 2);
640 c.section(SECTION_VALIDATOR_LIST_KEYS).values().size() == 2);
645 *
this,
"test_cfg",
"validators.txt");
647 *
this, vtg.
subdir(),
"",
"",
false);
650 auto const& c(rcg.
config());
651 BEAST_EXPECT(c.legacy(
"validators_file").empty());
652 BEAST_EXPECT(c.section(SECTION_VALIDATORS).values().size() == 8);
654 c.section(SECTION_VALIDATOR_LIST_SITES).values().size() == 2);
656 c.section(SECTION_VALIDATOR_LIST_KEYS).values().size() == 2);
662 *
this,
"test_cfg",
"validators.cfg");
665 *
this, vtg.
subdir(),
"validators.txt",
false);
670 auto const& c(rcg.
config());
671 BEAST_EXPECT(c.legacy(
"validators_file") == vtg.
validatorsFile());
672 BEAST_EXPECT(c.section(SECTION_VALIDATORS).values().size() == 8);
674 c.section(SECTION_VALIDATOR_LIST_SITES).values().size() == 2);
676 c.section(SECTION_VALIDATOR_LIST_KEYS).values().size() == 2);
681 boost::format cc(R
"rippleConfig(
686 n949f75evCHwgyP4fPVgaHqNHxUVN15PsJEZ3B3HnXPcPjcZAoy7
687 n9MD5h24qrQqiyBC8aeqqCWvpiBiYQ3jxSr91uiDvmrkyHRdYLUj
688 n9L81uNCaPgtUJfaHh89gmdvXKAmSt5Gdsw2g1iPWaPkAHW5Nm4C
689 n9KiYM9CgngLvtRCQHZwgC2gjpdaZcCcbt3VboxiNFcKuwFVujzS
690 n9LdgEtkmGB9E2h3K4Vp7iGUaKuq23Zr32ehxiU8FWY7xoxbWTSA
693 nHB1X37qrniVugfQcuBTAjswphC1drx7QjFFojJPZwKHHnt8kU7v
694 nHUkAWDR4cB8AgPg7VXMX6et8xRTQb2KJfgv1aBEXozwrawRKgMB
696 [validator_list_sites]
698 trustthesevalidators.gov
700 [validator_list_keys]
701 021A99A537FDEBC34E4FCA03B39BEADD04299BB19E85097EC92B15A3518801E566
704 *
this,
"test_cfg",
"validators.cfg");
720 boost::format cc(
"[validators_file]\n%1%\n");
723 *
this,
"test_cfg",
"validators.cfg");
725 auto const expectedError =
726 "The file specified in [validators_file] does not contain a "
727 "[validators], [validator_keys] or [validator_list_keys] "
740 BEAST_EXPECT(error == expectedError);
748 *
this,
"testSetup", explicitPath ?
"test_db" :
"",
"");
760 BEAST_EXPECT(!config.
quiet());
761 BEAST_EXPECT(!config.
silent());
764 BEAST_EXPECT(!config.
legacy(
"database_path").empty());
773 BEAST_EXPECT(config.
quiet());
774 BEAST_EXPECT(!config.
silent());
777 BEAST_EXPECT(!config.
legacy(
"database_path").empty());
786 BEAST_EXPECT(config.
quiet());
787 BEAST_EXPECT(config.
silent());
790 BEAST_EXPECT(!config.
legacy(
"database_path").empty());
799 BEAST_EXPECT(config.
quiet());
800 BEAST_EXPECT(config.
silent());
803 BEAST_EXPECT(!config.
legacy(
"database_path").empty());
812 BEAST_EXPECT(!config.
quiet());
813 BEAST_EXPECT(!config.
silent());
817 config.
legacy(
"database_path").empty() == !explicitPath);
826 BEAST_EXPECT(config.
quiet());
827 BEAST_EXPECT(!config.
silent());
831 config.
legacy(
"database_path").empty() == !explicitPath);
840 BEAST_EXPECT(config.
quiet());
841 BEAST_EXPECT(config.
silent());
845 config.
legacy(
"database_path").empty() == !explicitPath);
854 BEAST_EXPECT(config.
quiet());
855 BEAST_EXPECT(config.
silent());
859 config.
legacy(
"database_path").empty() == !explicitPath);
867 auto const& conf = cfg.
config();
868 if (!BEAST_EXPECT(conf.exists(
"port_rpc")))
870 if (!BEAST_EXPECT(conf.exists(
"port_wss_admin")))
873 if (!unexcept([&]() {
parse_Port(rpc, conf[
"port_rpc"], log); }))
877 if (!unexcept([&]() {
parse_Port(wss, conf[
"port_wss_admin"], log); }))
915 cfg.exists(SECTION_IPS) &&
916 cfg.section(SECTION_IPS).lines().size() == 1 &&
917 cfg.section(SECTION_IPS).values().size() == 1);
919 cfg.exists(SECTION_IPS_FIXED) &&
920 cfg.section(SECTION_IPS_FIXED).lines().size() == 2 &&
921 cfg.section(SECTION_IPS_FIXED).values().size() == 2);
950 anotherserversansport
951 anotherserverwithport:12
961 2001:db8:3333:4444:5555:6666:7777:8888:12345
962 [2001:db8:3333:4444:5555:6666:7777:8888]:1
971 cfg.
exists(SECTION_IPS) &&
975 cfg.
exists(SECTION_IPS_FIXED) &&
978 BEAST_EXPECT(cfg.
IPS[0] ==
"r.ripple.com 51235");
980 BEAST_EXPECT(cfg.
IPS_FIXED[0] ==
"s1.ripple.com 51235");
981 BEAST_EXPECT(cfg.
IPS_FIXED[1] ==
"s2.ripple.com 51235");
982 BEAST_EXPECT(cfg.
IPS_FIXED[2] ==
"anotherserversansport");
983 BEAST_EXPECT(cfg.
IPS_FIXED[3] ==
"anotherserverwithport 12");
984 BEAST_EXPECT(cfg.
IPS_FIXED[4] ==
"1.1.1.1 1");
985 BEAST_EXPECT(cfg.
IPS_FIXED[5] ==
"1.1.1.1 1");
986 BEAST_EXPECT(cfg.
IPS_FIXED[6] ==
"12.34.12.123 12345");
987 BEAST_EXPECT(cfg.
IPS_FIXED[7] ==
"12.34.12.123 12345");
991 BEAST_EXPECT(cfg.
IPS_FIXED[9] ==
"2001:db8::");
992 BEAST_EXPECT(cfg.
IPS_FIXED[10] ==
"::1");
993 BEAST_EXPECT(cfg.
IPS_FIXED[11] ==
"::1:12345");
994 BEAST_EXPECT(cfg.
IPS_FIXED[12] ==
"[::1]:12345");
997 "2001:db8:3333:4444:5555:6666:7777:8888:12345");
999 cfg.
IPS_FIXED[14] ==
"[2001:db8:3333:4444:5555:6666:7777:8888]:1");
1005 struct TestCommentData
1014 {{
"password = aaaa\\#bbbb",
"password",
"aaaa#bbbb",
false},
1015 {
"password = aaaa#bbbb",
"password",
"aaaa",
true},
1016 {
"password = aaaa #bbbb",
"password",
"aaaa",
true},
1018 {
"password = #aaaa #bbbb",
"",
"password =",
true},
1019 {
"password = aaaa\\# #bbbb",
"password",
"aaaa#",
true},
1020 {
"password = aaaa\\##bbbb",
"password",
"aaaa#",
true},
1021 {
"aaaa#bbbb",
"",
"aaaa",
true},
1022 {
"aaaa\\#bbbb",
"",
"aaaa#bbbb",
false},
1023 {
"aaaa\\##bbbb",
"",
"aaaa#",
true},
1024 {
"aaaa #bbbb",
"",
"aaaa",
true},
1025 {
"1 #comment",
"",
"1",
true},
1026 {
"#whole thing is comment",
"",
"",
false},
1027 {
" #whole comment with space",
"",
"",
false}}};
1029 for (
auto const& t : tests)
1032 s.append(t.line.data());
1033 BEAST_EXPECT(s.had_trailing_comments() == t.had_comment);
1034 if (t.field.empty())
1036 BEAST_EXPECTS(s.legacy() == t.expect, s.legacy());
1041 BEAST_EXPECTS(
set(field, t.field.data(), s), t.line);
1042 BEAST_EXPECTS(field == t.expect, t.line);
1048 s.append(
"online_delete = 3000");
1050 BEAST_EXPECT(
set(od,
"online_delete", s));
1051 BEAST_EXPECTS(od == 3000, *(s.get<
std::string>(
"online_delete")));
1056 s.append(
"online_delete = 2000 #my comment on this");
1058 BEAST_EXPECT(
set(od,
"online_delete", s));
1059 BEAST_EXPECTS(od == 2000, *(s.get<
std::string>(
"online_delete")));
1066 using namespace std::string_literals;
1067 Section s{
"MySection"};
1068 s.append(
"a_string = mystring");
1069 s.append(
"positive_int = 2");
1070 s.append(
"negative_int = -3");
1071 s.append(
"bool_ish = 1");
1074 auto val_1 =
"value 1"s;
1075 BEAST_EXPECT(
set(val_1,
"a_string", s));
1076 BEAST_EXPECT(val_1 ==
"mystring");
1078 auto val_2 =
"value 2"s;
1079 BEAST_EXPECT(!
set(val_2,
"not_a_key", s));
1080 BEAST_EXPECT(val_2 ==
"value 2");
1081 BEAST_EXPECT(!
set(val_2,
"default"s,
"not_a_key", s));
1082 BEAST_EXPECT(val_2 ==
"default");
1084 auto val_3 = get<std::string>(s,
"a_string");
1085 BEAST_EXPECT(val_3 ==
"mystring");
1086 auto val_4 = get<std::string>(s,
"not_a_key");
1087 BEAST_EXPECT(val_4 ==
"");
1088 auto val_5 = get<std::string>(s,
"not_a_key",
"default");
1089 BEAST_EXPECT(val_5 ==
"default");
1091 auto val_6 =
"value 6"s;
1093 BEAST_EXPECT(val_6 ==
"mystring");
1095 auto val_7 =
"value 7"s;
1097 BEAST_EXPECT(val_7 ==
"value 7");
1102 BEAST_EXPECT(
set(val_1,
"positive_int", s));
1103 BEAST_EXPECT(val_1 == 2);
1106 BEAST_EXPECT(
set(val_2,
"negative_int", s));
1107 BEAST_EXPECT(val_2 == -3);
1110 BEAST_EXPECT(!
set(val_3,
"a_string", s));
1111 BEAST_EXPECT(val_3 == 3);
1113 auto val_4 = get<int>(s,
"positive_int");
1114 BEAST_EXPECT(val_4 == 2);
1115 auto val_5 = get<int>(s,
"not_a_key");
1116 BEAST_EXPECT(val_5 == 0);
1117 auto val_6 = get<int>(s,
"not_a_key", 5);
1118 BEAST_EXPECT(val_6 == 5);
1119 auto val_7 = get<int>(s,
"a_string", 6);
1120 BEAST_EXPECT(val_7 == 6);
1124 BEAST_EXPECT(val_8 == 2);
1128 BEAST_EXPECT(val_9 == 9);
1132 BEAST_EXPECT(val_10 == 10);
1134 BEAST_EXPECT(s.get<
int>(
"not_a_key") == std::nullopt);
1137 s.get<
int>(
"a_string");
1140 catch (boost::bad_lexical_cast&)
1147 bool flag_1 =
false;
1149 BEAST_EXPECT(flag_1 ==
true);
1151 bool flag_2 =
false;
1153 BEAST_EXPECT(flag_2 ==
false);
1160 testcase(
"amendment");
1170 {
"seconds", 1, 15 * 60,
false},
1171 {
"minutes", 60, 14,
false},
1172 {
"minutes", 60, 15,
true},
1173 {
"hours", 3600, 10,
true},
1174 {
"days", 86400, 10,
true},
1175 {
"weeks", 604800, 2,
true},
1176 {
"months", 2592000, 1,
false},
1177 {
"years", 31536000, 1,
false}};
1180 for (
auto& [unit, sec, val, shouldPass] : units)
1184 [amendment_majority_time]
1191 c.loadFromString(toLoad);
1194 c.AMENDMENT_MAJORITY_TIME.count() == val * sec);
1211 testcase(
"overlay: unknown time");
1218 c.loadFromString(
"[overlay]\nmax_unknown_time=" + value);
1219 return c.MAX_UNKNOWN_TIME;
1228 BEAST_EXPECT(!testUnknown(
"none"));
1229 BEAST_EXPECT(!testUnknown(
"0.5"));
1230 BEAST_EXPECT(!testUnknown(
"180 seconds"));
1231 BEAST_EXPECT(!testUnknown(
"9 minutes"));
1234 BEAST_EXPECT(!testUnknown(
"299"));
1243 BEAST_EXPECT(!testUnknown(
"1801"));
1245 testcase(
"overlay: diverged time");
1263 BEAST_EXPECT(!testDiverged(
"none"));
1264 BEAST_EXPECT(!testDiverged(
"0.5"));
1265 BEAST_EXPECT(!testDiverged(
"180 seconds"));
1266 BEAST_EXPECT(!testDiverged(
"9 minutes"));
1269 BEAST_EXPECT(!testDiverged(
"0"));
1270 BEAST_EXPECT(!testDiverged(
"59"));
1279 BEAST_EXPECT(!testDiverged(
"901"));
1287 testValidatorKeys();
1288 testValidatorsFile();