21#include <xrpld/app/misc/ValidatorList.h>
22#include <xrpld/overlay/detail/ProtocolMessage.h>
23#include <xrpl/basics/Slice.h>
24#include <xrpl/basics/base64.h>
25#include <xrpl/basics/strHex.h>
26#include <xrpl/protocol/HashPrefix.h>
27#include <xrpl/protocol/PublicKey.h>
28#include <xrpl/protocol/SecretKey.h>
29#include <xrpl/protocol/Sign.h>
30#include <xrpl/protocol/digest.h>
31#include <xrpl/protocol/jss.h>
32#include <xrpl/protocol/messages.h>
34#include <boost/beast/core/multi_buffer.hpp>
75 st[sfSigningPubKey] = spk;
140 data +=
",\"validators\":[";
142 for (
auto const& val : validators)
144 data +=
"{\"validation_public_key\":\"" +
strHex(val.masterPublic) +
145 "\",\"manifest\":\"" + val.manifest +
"\"},";
167 for (
auto const& pk : pks)
193 auto& app = env.
app();
195 auto trustedKeys = std::make_unique<ValidatorList>(
199 app.config().legacy(
"database_path"),
201 BEAST_EXPECT(trustedKeys->quorum() == 1);
205 auto trustedKeys = std::make_unique<ValidatorList>(
209 app.config().legacy(
"database_path"),
212 BEAST_EXPECT(trustedKeys->quorum() == minQuorum);
223 auto& app = env.
app();
228 auto const localSigningPublicOuter = localSigningKeys.first;
229 auto const localSigningSecret = localSigningKeys.second;
231 auto const localMasterPublic =
237 localSigningPublicOuter,
241 auto format = [](
PublicKey const& publicKey,
242 char const* comment =
nullptr) {
254 while (configList.
size() != 8)
259 {format(configList[0]),
260 format(configList[1],
" Comment"),
261 format(configList[2],
" Multi Word Comment"),
262 format(configList[3],
" Leading Whitespace"),
263 format(configList[4],
" Trailing Whitespace "),
264 format(configList[5],
" Leading & Trailing Whitespace "),
267 " Leading, Trailing & Internal Whitespace "),
268 format(configList[7],
" ")});
272 auto trustedKeys = std::make_unique<ValidatorList>(
276 app.config().legacy(
"database_path"),
281 trustedKeys->load({}, emptyCfgKeys, emptyCfgPublishers));
284 BEAST_EXPECT(trustedKeys->load(
285 localSigningPublicOuter, emptyCfgKeys, emptyCfgPublishers));
286 BEAST_EXPECT(trustedKeys->listed(localSigningPublicOuter));
289 BEAST_EXPECT(trustedKeys->load(
290 localSigningPublicOuter, emptyCfgKeys, emptyCfgPublishers));
292 BEAST_EXPECT(trustedKeys->listed(localMasterPublic));
293 BEAST_EXPECT(trustedKeys->listed(localSigningPublicOuter));
298 auto trustedKeys = std::make_unique<ValidatorList>(
302 app.config().legacy(
"database_path"),
305 BEAST_EXPECT(trustedKeys->load({}, cfgKeys, emptyCfgPublishers));
307 for (
auto const& n : configList)
308 BEAST_EXPECT(trustedKeys->listed(n));
315 {format(masterNode1), format(masterNode2,
" Comment")});
317 trustedKeys->load({}, cfgMasterKeys, emptyCfgPublishers));
318 BEAST_EXPECT(trustedKeys->listed(masterNode1));
319 BEAST_EXPECT(trustedKeys->listed(masterNode2));
323 !trustedKeys->load({}, {
"NotAPublicKey"}, emptyCfgPublishers));
324 BEAST_EXPECT(!trustedKeys->load(
325 {}, {format(randomNode(),
"!")}, emptyCfgPublishers));
329 BEAST_EXPECT(!trustedKeys->load(
331 {format(randomNode(),
"!"), format(goodKey)},
332 emptyCfgPublishers));
333 BEAST_EXPECT(!trustedKeys->listed(goodKey));
338 auto trustedKeys = std::make_unique<ValidatorList>(
342 app.config().legacy(
"database_path"),
345 auto const localSigningPublic =
348 BEAST_EXPECT(trustedKeys->load(
349 *localSigningPublic, cfgKeys, emptyCfgPublishers));
351 BEAST_EXPECT(trustedKeys->localPublicKey() == localSigningPublic);
352 BEAST_EXPECT(trustedKeys->listed(*localSigningPublic));
353 for (
auto const& n : configList)
354 BEAST_EXPECT(trustedKeys->listed(n));
359 auto trustedKeys = std::make_unique<ValidatorList>(
363 app.config().legacy(
"database_path"),
367 BEAST_EXPECT(trustedKeys->load(
368 localSigningPublic, cfgKeys, emptyCfgPublishers));
370 BEAST_EXPECT(trustedKeys->localPublicKey() == localSigningPublic);
371 BEAST_EXPECT(trustedKeys->listed(localSigningPublic));
372 for (
auto const& n : configList)
373 BEAST_EXPECT(trustedKeys->listed(n));
378 auto trustedKeys = std::make_unique<ValidatorList>(
382 app.config().legacy(
"database_path"),
387 BEAST_EXPECT(trustedKeys->load(
388 localSigningPublicOuter, cfgKeys, emptyCfgPublishers));
390 BEAST_EXPECT(trustedKeys->localPublicKey() == localMasterPublic);
391 BEAST_EXPECT(trustedKeys->listed(localSigningPublicOuter));
392 BEAST_EXPECT(trustedKeys->listed(localMasterPublic));
393 for (
auto const& n : configList)
394 BEAST_EXPECT(trustedKeys->listed(n));
398 auto trustedKeys = std::make_unique<ValidatorList>(
402 app.config().legacy(
"database_path"),
407 BEAST_EXPECT(!trustedKeys->load({}, emptyCfgKeys, badPublishers));
413 badPublishers.
clear();
414 for (
auto const& key : keys)
417 BEAST_EXPECT(!trustedKeys->load({}, emptyCfgKeys, badPublishers));
418 for (
auto const& key : keys)
419 BEAST_EXPECT(!trustedKeys->trustedPublisher(key));
423 for (
auto const& key : keys)
426 BEAST_EXPECT(trustedKeys->load({}, emptyCfgKeys, cfgPublishers));
427 for (
auto const& key : keys)
428 BEAST_EXPECT(trustedKeys->trustedPublisher(key));
435 auto trustedKeys = std::make_unique<ValidatorList>(
439 app.config().legacy(
"database_path"),
443 auto const pubRevokedPublic =
451 pubRevokedSigning.first,
452 pubRevokedSigning.second,
460 BEAST_EXPECT(trustedKeys->load({}, emptyCfgKeys, cfgPublishers));
462 BEAST_EXPECT(!trustedKeys->trustedPublisher(pubRevokedPublic));
463 BEAST_EXPECT(trustedKeys->trustedPublisher(legitKey));
471 using namespace std::chrono_literals;
475 auto checkAvailable =
477 auto const& trustedKeys,
478 auto const& hexPublic,
483 const auto available = trustedKeys->getAvailable(hexPublic);
489 BEAST_EXPECT(a[jss::public_key] == hexPublic);
490 BEAST_EXPECT(a[jss::manifest] ==
manifest);
493 BEAST_EXPECT(a[jss::version] == version);
496 BEAST_EXPECT(expected.size() == 1);
497 BEAST_EXPECT(a[jss::blob] == expected[0].first);
498 BEAST_EXPECT(a[jss::signature] == expected[0].second);
499 BEAST_EXPECT(!a.isMember(jss::blobs_v2));
501 else if (BEAST_EXPECT(a.isMember(jss::blobs_v2)))
503 BEAST_EXPECT(!a.isMember(jss::blob));
504 BEAST_EXPECT(!a.isMember(jss::signature));
505 auto const& blobs_v2 = a[jss::blobs_v2];
507 blobs_v2.isArray() &&
508 blobs_v2.size() == expected.size());
510 for (
unsigned int i = 0; i < expected.size(); ++i)
513 blobs_v2[i][jss::blob] == expected[i].first);
515 blobs_v2[i][jss::signature] ==
524 auto& app = env.
app();
525 auto trustedKeys = std::make_unique<ValidatorList>(
529 app.config().legacy(
"database_path"),
534 for (
auto const& val : list)
536 BEAST_EXPECT(trustedKeys->listed(val.masterPublic));
537 BEAST_EXPECT(trustedKeys->listed(val.signingPublic));
541 auto expectUntrusted =
543 for (
auto const& val : list)
545 BEAST_EXPECT(!trustedKeys->listed(val.masterPublic));
546 BEAST_EXPECT(!trustedKeys->listed(val.signingPublic));
551 auto const publisherPublic =
553 const auto hexPublic =
554 strHex(publisherPublic.begin(), publisherPublic.end());
559 pubSigningKeys1.first,
560 pubSigningKeys1.second,
566 BEAST_EXPECT(trustedKeys->load({}, emptyCfgKeys, cfgKeys1));
569 auto constexpr listSize = 20;
570 auto constexpr numLists = 9;
573 for (
auto i = 1; i <= numLists; ++i)
575 auto& list = lists[i];
576 list.reserve(listSize);
577 while (list.size() < listSize)
585 auto const version = 1;
586 auto const sequence1 = 1;
591 auto const expiredSig =
signList(expiredblob, pubSigningKeys1);
594 auto const sequence2 = 2;
597 auto const sig2 =
signList(blob2, pubSigningKeys1);
600 trustedKeys->applyLists(
603 {{expiredblob, expiredSig, {}}, {blob2, sig2, {}}},
609 expectTrusted(lists.at(2));
612 trustedKeys, hexPublic, manifest1, version, {{blob2, sig2}});
615 auto const version2 = 2;
616 auto const sequence7 = 7;
617 auto const effective7 = validUntil - 60s;
618 auto const expiration7 = effective7 + 3600s;
619 auto const blob7 = makeList(
622 expiration7.time_since_epoch().count(),
623 effective7.time_since_epoch().count());
624 auto const sig7 = signList(blob7, pubSigningKeys1);
626 auto const sequence8 = 8;
627 auto const effective8 = expiration7 - 60s;
628 auto const expiration8 = effective8 + 3600s;
629 auto const blob8 = makeList(
632 expiration8.time_since_epoch().count(),
633 effective8.time_since_epoch().count());
634 auto const sig8 = signList(blob8, pubSigningKeys1);
637 trustedKeys->applyLists(
640 {{blob7, sig7, {}}, {blob8, sig8, {}}},
643 ListDisposition::pending,
644 ListDisposition::pending);
646 expectUntrusted(lists.at(7));
647 expectUntrusted(lists.at(8));
650 auto const sequence6 = 6;
651 auto const effective6 = effective7 - 60s;
652 auto const expiration6 = effective6 + 3600s;
653 auto const blob6 = makeList(
656 expiration6.time_since_epoch().count(),
657 effective6.time_since_epoch().count());
658 auto const sig6 = signList(blob6, pubSigningKeys1);
661 auto const sequence6a = 5;
662 auto const effective6a = effective6 + 60s;
663 auto const expiration6a = effective6a + 3600s;
664 auto const blob6a = makeList(
667 expiration6a.time_since_epoch().count(),
668 effective6a.time_since_epoch().count());
669 auto const sig6a = signList(blob6a, pubSigningKeys1);
672 trustedKeys->applyLists(
675 {{blob6a, sig6a, {}}, {blob6, sig6, {}}},
678 ListDisposition::pending,
679 ListDisposition::pending);
681 expectUntrusted(lists.at(6));
682 expectTrusted(lists.at(2));
687 trustedKeys->applyLists(
690 {{blob7, sig7, {}}, {blob6, sig6, {}}},
693 ListDisposition::known_sequence,
694 ListDisposition::known_sequence);
696 expectUntrusted(lists.at(6));
697 expectUntrusted(lists.at(7));
698 expectTrusted(lists.at(2));
701 auto const untrustedManifest =
base64_encode(makeManifestString(
704 pubSigningKeys1.first,
705 pubSigningKeys1.second,
709 trustedKeys->applyLists(
710 untrustedManifest, version, {{blob2, sig2, {}}}, siteUri),
712 ListDisposition::untrusted,
713 ListDisposition::untrusted);
716 auto const badVersion = 666;
718 trustedKeys->applyLists(
719 manifest1, badVersion, {{blob2, sig2, {}}}, siteUri),
721 ListDisposition::unsupported_version,
722 ListDisposition::unsupported_version);
725 auto const sequence3 = 3;
726 auto const blob3 = makeList(
727 lists.at(3), sequence3, validUntil.time_since_epoch().count());
728 auto const sig3 = signList(blob3, pubSigningKeys1);
731 trustedKeys->applyLists(
732 manifest1, version, {{blob3, sig3, {}}}, siteUri),
734 ListDisposition::accepted,
735 ListDisposition::accepted);
737 expectUntrusted(lists.at(1));
738 expectUntrusted(lists.at(2));
739 expectTrusted(lists.at(3));
748 {{blob3, sig3}, {blob6, sig6}, {blob7, sig7}, {blob8, sig8}});
752 trustedKeys->applyLists(
755 {{blob2, sig2, {}}, {blob3, sig3, {}}},
758 ListDisposition::stale,
759 ListDisposition::same_sequence);
763 auto const pubSigningKeys2 =
randomKeyPair(KeyType::secp256k1);
767 pubSigningKeys2.first,
768 pubSigningKeys2.second,
771 auto const sequence4 = 4;
772 auto const blob4 = makeList(
773 lists.at(4), sequence4, validUntil.time_since_epoch().count());
774 auto const sig4 = signList(blob4, pubSigningKeys2);
777 trustedKeys->applyLists(
780 {{blob2, sig2, manifest1},
781 {blob3, sig3, manifest1},
785 ListDisposition::stale,
786 ListDisposition::accepted);
788 expectUntrusted(lists.at(2));
789 expectUntrusted(lists.at(3));
790 expectTrusted(lists.at(4));
797 {{blob4, sig4}, {blob6, sig6}, {blob7, sig7}, {blob8, sig8}});
799 auto const sequence5 = 5;
800 auto const blob5 = makeList(
801 lists.at(5), sequence5, validUntil.time_since_epoch().count());
802 auto const badSig = signList(blob5, pubSigningKeys1);
804 trustedKeys->applyLists(
805 manifest1, version, {{blob5, badSig, {}}}, siteUri),
807 ListDisposition::invalid,
808 ListDisposition::invalid);
810 expectUntrusted(lists.at(2));
811 expectUntrusted(lists.at(3));
812 expectTrusted(lists.at(4));
813 expectUntrusted(lists.at(5));
817 trustedKeys->applyLists(
820 {{blob7, sig7, {}}, {blob8, sig8, {}}},
823 ListDisposition::invalid,
824 ListDisposition::invalid);
826 expectTrusted(lists.at(4));
827 expectUntrusted(lists.at(7));
828 expectUntrusted(lists.at(8));
833 trustedKeys->updateTrusted(
838 env.app().getHashRouter());
840 expectUntrusted(lists.at(3));
841 expectTrusted(lists.at(6));
848 {{blob6, sig6}, {blob7, sig7}, {blob8, sig8}});
854 env.timeKeeper().set(effective8);
855 trustedKeys->updateTrusted(
860 env.app().getHashRouter());
862 expectUntrusted(lists.at(6));
863 expectUntrusted(lists.at(7));
864 expectTrusted(lists.at(8));
866 checkAvailable(trustedKeys, hexPublic, manifest2, 2, {{blob8, sig8}});
872 auto const sig8_2 = signList(blob8, pubSigningKeys2);
875 trustedKeys->applyLists(
878 {{blob8, sig8, manifest1}, {blob8, sig8_2, {}}},
881 ListDisposition::invalid,
882 ListDisposition::same_sequence);
884 expectTrusted(lists.at(8));
886 checkAvailable(trustedKeys, hexPublic, manifest2, 2, {{blob8, sig8}});
890 auto const signingKeysMax =
randomKeyPair(KeyType::secp256k1);
892 makeRevocationString(publisherPublic, publisherSecret));
894 auto const sequence9 = 9;
895 auto const blob9 = makeList(
896 lists.at(9), sequence9, validUntil.time_since_epoch().count());
897 auto const sig9 = signList(blob9, signingKeysMax);
900 trustedKeys->applyLists(
901 maxManifest, version, {{blob9, sig9, {}}}, siteUri),
903 ListDisposition::untrusted,
904 ListDisposition::untrusted);
906 BEAST_EXPECT(!trustedKeys->trustedPublisher(publisherPublic));
907 for (
auto const& [num, list] : lists)
910 expectUntrusted(list);
913 checkAvailable(trustedKeys, hexPublic, manifest2, 0, {});
919 testcase(
"GetAvailable");
920 using namespace std::chrono_literals;
926 auto& app = env.
app();
927 auto trustedKeys = std::make_unique<ValidatorList>(
931 app.config().legacy(
"database_path"),
935 auto const publisherPublic =
937 const auto hexPublic =
938 strHex(publisherPublic.begin(), publisherPublic.end());
939 auto const pubSigningKeys1 =
randomKeyPair(KeyType::secp256k1);
943 pubSigningKeys1.first,
944 pubSigningKeys1.second,
950 BEAST_EXPECT(trustedKeys->load({}, emptyCfgKeys, cfgKeys1));
953 auto constexpr listSize = 20;
956 while (list.
size() < listSize)
966 auto const sig = signList(blob, pubSigningKeys1);
970 auto const available = trustedKeys->getAvailable(hexPublic);
975 trustedKeys->applyLists(
manifest, 1, {{blob, sig, {}}}, siteUri)
976 .bestDisposition() == ListDisposition::accepted);
981 trustedKeys->getAvailable(hexPublic +
"invalid", 1);
982 BEAST_EXPECT(!available);
989 const auto hexBad =
strHex(badPublic.begin(), badPublic.end());
991 auto const available = trustedKeys->getAvailable(hexBad, 1);
992 BEAST_EXPECT(!available);
996 auto const available = trustedKeys->getAvailable(hexPublic, 0);
997 if (BEAST_EXPECT(available))
999 auto const& a = *available;
1005 auto const available = trustedKeys->getAvailable(hexPublic, 3);
1006 if (BEAST_EXPECT(available))
1014 auto const available = trustedKeys->getAvailable(hexPublic, 1);
1015 if (BEAST_EXPECT(available))
1018 BEAST_EXPECT(a[jss::public_key] == hexPublic);
1019 BEAST_EXPECT(a[jss::manifest] == manifest);
1020 BEAST_EXPECT(a[jss::version] == 1);
1022 BEAST_EXPECT(a[jss::blob] == blob);
1023 BEAST_EXPECT(a[jss::signature] == sig);
1024 BEAST_EXPECT(!a.isMember(jss::blobs_v2));
1030 auto const available = trustedKeys->getAvailable(hexPublic, 2);
1031 if (BEAST_EXPECT(available))
1034 BEAST_EXPECT(a[jss::public_key] == hexPublic);
1035 BEAST_EXPECT(a[jss::manifest] == manifest);
1036 BEAST_EXPECT(a[jss::version] == 2);
1038 if (BEAST_EXPECT(a.isMember(jss::blobs_v2)))
1040 BEAST_EXPECT(!a.isMember(jss::blob));
1041 BEAST_EXPECT(!a.isMember(jss::signature));
1042 auto const& blobs_v2 = a[jss::blobs_v2];
1043 BEAST_EXPECT(blobs_v2.isArray() && blobs_v2.size() == 1);
1045 BEAST_EXPECT(blobs_v2[0u][jss::blob] == blob);
1046 BEAST_EXPECT(blobs_v2[0u][jss::signature] == sig);
1055 testcase(
"Update trusted");
1057 std::string const siteUri =
"testUpdateTrusted.test";
1061 auto& app = env.
app();
1062 auto trustedKeysOuter = std::make_unique<ValidatorList>(
1066 app.config().legacy(
"database_path"),
1078 while (cfgKeys.
size() != maxKeys)
1080 auto const valKey = randomNode();
1082 if (cfgKeys.
size() <= maxKeys - 5)
1089 trustedKeysOuter->load({}, cfgKeys, cfgPublishersOuter));
1093 TrustChanges changes = trustedKeysOuter->updateTrusted(
1094 activeValidatorsOuter,
1100 for (
auto const& val : unseenValidators)
1101 activeValidatorsOuter.
emplace(val);
1103 BEAST_EXPECT(changes.
added == activeValidatorsOuter);
1104 BEAST_EXPECT(changes.
removed.empty());
1106 trustedKeysOuter->quorum() ==
std::ceil(cfgKeys.
size() * 0.8f));
1107 for (
auto const& val : cfgKeys)
1109 if (
auto const valKey =
1110 parseBase58<PublicKey>(TokenType::NodePublic, val))
1112 BEAST_EXPECT(trustedKeysOuter->listed(*valKey));
1113 BEAST_EXPECT(trustedKeysOuter->trusted(*valKey));
1119 changes = trustedKeysOuter->updateTrusted(
1120 activeValidatorsOuter,
1125 BEAST_EXPECT(changes.
added.empty());
1126 BEAST_EXPECT(changes.
removed.empty());
1128 trustedKeysOuter->quorum() ==
std::ceil(cfgKeys.
size() * 0.8f));
1133 auto const masterPublic =
1137 {
toBase58(TokenType::NodePublic, masterPublic)});
1140 trustedKeysOuter->load({}, cfgKeys, cfgPublishersOuter));
1142 auto const signingKeys1 =
randomKeyPair(KeyType::secp256k1);
1143 auto const signingPublic1 = signingKeys1.first;
1147 TrustChanges changes = trustedKeysOuter->updateTrusted(
1148 activeValidatorsOuter,
1153 BEAST_EXPECT(changes.
added == asNodeIDs({masterPublic}));
1154 BEAST_EXPECT(changes.
removed.empty());
1156 trustedKeysOuter->quorum() ==
std::ceil((maxKeys + 1) * 0.8f));
1157 BEAST_EXPECT(trustedKeysOuter->listed(masterPublic));
1158 BEAST_EXPECT(trustedKeysOuter->trusted(masterPublic));
1159 BEAST_EXPECT(!trustedKeysOuter->listed(signingPublic1));
1160 BEAST_EXPECT(!trustedKeysOuter->trusted(signingPublic1));
1167 signingKeys1.second,
1172 ManifestDisposition::accepted);
1173 BEAST_EXPECT(trustedKeysOuter->listed(masterPublic));
1174 BEAST_EXPECT(trustedKeysOuter->trusted(masterPublic));
1175 BEAST_EXPECT(trustedKeysOuter->listed(signingPublic1));
1176 BEAST_EXPECT(trustedKeysOuter->trusted(signingPublic1));
1180 auto const signingKeys2 =
randomKeyPair(KeyType::secp256k1);
1181 auto const signingPublic2 = signingKeys2.first;
1186 signingKeys2.second,
1190 ManifestDisposition::accepted);
1191 BEAST_EXPECT(trustedKeysOuter->listed(masterPublic));
1192 BEAST_EXPECT(trustedKeysOuter->trusted(masterPublic));
1193 BEAST_EXPECT(trustedKeysOuter->listed(signingPublic2));
1194 BEAST_EXPECT(trustedKeysOuter->trusted(signingPublic2));
1195 BEAST_EXPECT(!trustedKeysOuter->listed(signingPublic1));
1196 BEAST_EXPECT(!trustedKeysOuter->trusted(signingPublic1));
1199 auto const signingKeysMax =
randomKeyPair(KeyType::secp256k1);
1200 auto const signingPublicMax = signingKeysMax.first;
1203 makeRevocationString(masterPublic, masterPrivate));
1205 BEAST_EXPECT(mMax->revoked());
1208 ManifestDisposition::accepted);
1210 manifestsOuter.
getSigningKey(masterPublic) == masterPublic);
1211 BEAST_EXPECT(manifestsOuter.
revoked(masterPublic));
1214 BEAST_EXPECT(trustedKeysOuter->listed(masterPublic));
1215 BEAST_EXPECT(trustedKeysOuter->trusted(masterPublic));
1217 changes = trustedKeysOuter->updateTrusted(
1218 activeValidatorsOuter,
1223 BEAST_EXPECT(changes.
removed == asNodeIDs({masterPublic}));
1224 BEAST_EXPECT(changes.
added.empty());
1226 trustedKeysOuter->quorum() ==
std::ceil(maxKeys * 0.8f));
1227 BEAST_EXPECT(trustedKeysOuter->listed(masterPublic));
1228 BEAST_EXPECT(!trustedKeysOuter->trusted(masterPublic));
1229 BEAST_EXPECT(!trustedKeysOuter->listed(signingPublicMax));
1230 BEAST_EXPECT(!trustedKeysOuter->trusted(signingPublicMax));
1231 BEAST_EXPECT(!trustedKeysOuter->listed(signingPublic2));
1232 BEAST_EXPECT(!trustedKeysOuter->trusted(signingPublic2));
1233 BEAST_EXPECT(!trustedKeysOuter->listed(signingPublic1));
1234 BEAST_EXPECT(!trustedKeysOuter->trusted(signingPublic1));
1239 auto trustedKeys = std::make_unique<ValidatorList>(
1243 app.config().legacy(
"database_path"),
1246 auto const publisherPublic =
1252 BEAST_EXPECT(trustedKeys->load({}, emptyCfgKeys, cfgPublishers));
1255 activeValidatorsOuter,
1260 BEAST_EXPECT(changes.
removed.empty());
1261 BEAST_EXPECT(changes.
added.empty());
1263 trustedKeys->quorum() ==
1270 auto trustedKeys = std::make_unique<ValidatorList>(
1274 app.config().legacy(
"database_path"),
1285 while (cfgKeys.
size() < n)
1287 auto const valKey = randomNode();
1296 BEAST_EXPECT(trustedKeys->load({}, cfgKeys, cfgPublishersOuter));
1304 BEAST_EXPECT(changes.
removed.empty());
1305 BEAST_EXPECT(changes.
added == expectedTrusted);
1306 BEAST_EXPECT(trustedKeys->quorum() == minQuorum);
1309 activeValidators.
emplace(toBeSeen);
1310 changes = trustedKeys->updateTrusted(
1316 BEAST_EXPECT(changes.
removed.empty());
1317 BEAST_EXPECT(changes.
added.empty());
1318 BEAST_EXPECT(trustedKeys->quorum() == minQuorum);
1322 auto trustedKeys = std::make_unique<ValidatorList>(
1326 app.config().legacy(
"database_path"),
1330 auto const publisherKeys =
randomKeyPair(KeyType::secp256k1);
1331 auto const pubSigningKeys =
randomKeyPair(KeyType::secp256k1);
1333 publisherKeys.first,
1334 publisherKeys.second,
1335 pubSigningKeys.first,
1336 pubSigningKeys.second,
1341 BEAST_EXPECT(trustedKeys->load({}, emptyCfgKeys, cfgKeys));
1345 asNodeIDs({list[0].masterPublic, list[1].masterPublic}));
1348 auto const version = 1;
1349 auto const sequence = 1;
1350 using namespace std::chrono_literals;
1355 auto const sig = signList(blob, pubSigningKeys);
1358 ListDisposition::accepted ==
1360 ->applyLists(
manifest, version, {{blob,
sig, {}}}, siteUri)
1361 .bestDisposition());
1369 BEAST_EXPECT(changes.
removed.empty());
1370 BEAST_EXPECT(changes.
added == activeValidators);
1373 BEAST_EXPECT(trustedKeys->trusted(val.masterPublic));
1374 BEAST_EXPECT(trustedKeys->trusted(val.signingPublic));
1376 BEAST_EXPECT(trustedKeys->quorum() == 2);
1379 changes = trustedKeys->updateTrusted(
1385 BEAST_EXPECT(changes.
removed == activeValidators);
1386 BEAST_EXPECT(changes.
added.empty());
1387 BEAST_EXPECT(!trustedKeys->trusted(list[0].masterPublic));
1388 BEAST_EXPECT(!trustedKeys->trusted(list[1].masterPublic));
1390 trustedKeys->quorum() ==
1396 auto const sequence2 = 2;
1399 auto const blob2 = makeList(
1401 auto const sig2 = signList(blob2, pubSigningKeys);
1404 ListDisposition::accepted ==
1407 manifest, version, {{blob2, sig2, {}}}, siteUri)
1408 .bestDisposition());
1410 changes = trustedKeys->updateTrusted(
1416 BEAST_EXPECT(changes.
removed.empty());
1419 asNodeIDs({list2[0].masterPublic, list2[1].masterPublic}));
1422 BEAST_EXPECT(trustedKeys->trusted(val.masterPublic));
1423 BEAST_EXPECT(trustedKeys->trusted(val.signingPublic));
1425 BEAST_EXPECT(!trustedKeys->trusted(list[1].masterPublic));
1426 BEAST_EXPECT(!trustedKeys->trusted(list[1].signingPublic));
1427 BEAST_EXPECT(trustedKeys->quorum() == 2);
1431 auto trustedKeys = std::make_unique<ValidatorList>(
1435 app.config().legacy(
"database_path"),
1447 auto const valKey = randomNode();
1451 BEAST_EXPECT(trustedKeys->load({}, cfgKeys, cfgPublishers));
1458 BEAST_EXPECT(changes.
removed.empty());
1459 BEAST_EXPECT(changes.
added == asNodeIDs({valKey}));
1462 for (
auto const& key : activeKeys)
1463 BEAST_EXPECT(trustedKeys->trusted(key));
1468 auto trustedKeys = std::make_unique<ValidatorList>(
1472 app.config().legacy(
"database_path"),
1475 auto const localKey = randomNode();
1480 toBase58(TokenType::NodePublic, localKey)};
1483 while (cfgKeys.size() < cfgKeys.capacity())
1485 auto const valKey = randomNode();
1486 cfgKeys.push_back(
toBase58(TokenType::NodePublic, valKey));
1491 trustedKeys->load(localKey, cfgKeys, cfgPublishers));
1498 BEAST_EXPECT(changes.
removed.empty());
1499 if (cfgKeys.size() > 2)
1500 BEAST_EXPECT(changes.
added == asNodeIDs({valKey}));
1503 changes.
added == asNodeIDs({localKey, valKey}));
1506 trustedKeys->quorum() ==
std::ceil(cfgKeys.size() * 0.8f));
1508 for (
auto const& key : activeKeys)
1509 BEAST_EXPECT(trustedKeys->trusted(key));
1515 auto trustedKeys = std::make_unique<ValidatorList>(
1519 app.config().legacy(
"database_path"),
1526 while (valKeys.
size() != maxKeys)
1533 auto addPublishedList = [
this,
1539 auto const publisherPublic =
1541 auto const pubSigningKeys =
randomKeyPair(KeyType::secp256k1);
1545 pubSigningKeys.first,
1546 pubSigningKeys.second,
1550 {
strHex(publisherPublic)});
1554 trustedKeys->load({}, emptyCfgKeys, cfgPublishers));
1556 auto const version = 1;
1557 auto const sequence = 1;
1558 using namespace std::chrono_literals;
1561 auto const blob = makeList(
1563 auto const sig = signList(blob, pubSigningKeys);
1566 ListDisposition::accepted ==
1570 .bestDisposition());
1574 for (
auto i = 0; i < 3; ++i)
1588 for (
auto const& val : valKeys)
1590 BEAST_EXPECT(trustedKeys->trusted(val.masterPublic));
1593 BEAST_EXPECT(changes.
added == added);
1594 BEAST_EXPECT(changes.
removed.empty());
1601 testcase(
"Expires");
1606 auto& app = env.
app();
1608 auto toStr = [](
PublicKey const& publicKey) {
1609 return toBase58(TokenType::NodePublic, publicKey);
1615 auto trustedKeys = std::make_unique<ValidatorList>(
1619 app.config().legacy(
"database_path"),
1623 BEAST_EXPECT(trustedKeys->expires() == std::nullopt);
1626 PublicKey localCfgListed = randomNode();
1627 trustedKeys->load({}, {toStr(localCfgListed)}, {});
1629 trustedKeys->expires() &&
1630 trustedKeys->expires().value() == NetClock::time_point::max());
1631 BEAST_EXPECT(trustedKeys->listed(localCfgListed));
1637 auto trustedKeys = std::make_unique<ValidatorList>(
1641 app.config().legacy(
"database_path"),
1658 using namespace std::chrono_literals;
1659 auto addPublishedList = [
this, &env, &trustedKeys, &validators]() {
1661 auto const publisherPublic =
1663 auto const pubSigningKeys =
randomKeyPair(KeyType::secp256k1);
1667 pubSigningKeys.first,
1668 pubSigningKeys.second,
1672 {
strHex(publisherPublic)});
1676 trustedKeys->load({}, emptyCfgKeys, cfgPublishers));
1678 auto const version = 2;
1679 auto const sequence1 = 1;
1682 auto const blob1 = makeList(
1686 auto const sig1 = signList(blob1, pubSigningKeys);
1690 auto const sequence2 = 2;
1691 auto const blob2 = makeList(
1696 auto const sig2 = signList(blob2, pubSigningKeys);
1698 return PreparedList{
1701 {{blob1, sig1, {}}, {blob2, sig2, {}}},
1703 {expiration1, expiration2}};
1707 PreparedList prep1 = addPublishedList();
1709 PreparedList prep2 = addPublishedList();
1712 BEAST_EXPECT(trustedKeys->expires() == std::nullopt);
1716 trustedKeys->applyLists(
1717 prep1.manifest, prep1.version, prep1.blobs, siteUri),
1718 prep1.publisherPublic,
1719 ListDisposition::pending,
1720 ListDisposition::accepted);
1724 BEAST_EXPECT(trustedKeys->expires() == std::nullopt);
1728 trustedKeys->applyLists(
1729 prep2.manifest, prep2.version, prep2.blobs, siteUri),
1730 prep2.publisherPublic,
1731 ListDisposition::pending,
1732 ListDisposition::accepted);
1735 trustedKeys->expires() &&
1736 trustedKeys->expires().value() == prep1.expirations.back());
1742 auto changes = trustedKeys->updateTrusted(
1749 trustedKeys->expires() &&
1750 trustedKeys->expires().value() == prep1.expirations.back());
1751 BEAST_EXPECT(!changes.added.empty());
1752 BEAST_EXPECT(changes.removed.empty());
1759 auto changes = trustedKeys->updateTrusted(
1766 trustedKeys->expires() &&
1767 trustedKeys->expires().value() == prep1.expirations.back());
1768 BEAST_EXPECT(changes.added.empty());
1769 BEAST_EXPECT(changes.removed.empty());
1777 testcase(
"NegativeUNL");
1781 auto createValidatorList =
1785 auto trustedKeys = std::make_shared<ValidatorList>(
1799 auto const valKey = randomNode();
1803 if (trustedKeys->load({}, cfgKeys, cfgPublishers))
1805 trustedKeys->updateTrusted(
1811 if (minimumQuorum == trustedKeys->quorum() ||
1837 for (
auto us : unlSizes)
1839 for (
auto np : nUnlPercent)
1841 auto validators = createValidatorList(us);
1842 BEAST_EXPECT(validators);
1846 auto unl = validators->getTrustedMasterKeys();
1848 auto it = unl.
begin();
1854 validators->setNegativeUNL(nUnl);
1855 validators->updateTrusted(
1862 validators->quorum() ==
1864 std::max((us - nUnlSize) * 0.8f, us * 0.6f))));
1872 auto validators = createValidatorList(60);
1873 BEAST_EXPECT(validators);
1877 auto unl = validators->getTrustedMasterKeys();
1878 BEAST_EXPECT(unl.size() == 60);
1885 auto it = unl.
begin();
1891 validators->setNegativeUNL(nUnl);
1892 auto nUnl_temp = validators->getNegativeUNL();
1893 if (nUnl_temp.size() == nUnl.
size())
1895 for (
auto& n : nUnl_temp)
1897 if (nUnl.
find(n) == nUnl.
end())
1900 validators->updateTrusted(
1906 return validators->quorum() == quorum;
1910 BEAST_EXPECT(nUnlChange(0, 48));
1911 BEAST_EXPECT(nUnlChange(30, 36));
1912 BEAST_EXPECT(nUnlChange(18, 36));
1913 BEAST_EXPECT(nUnlChange(12, 39));
1919 auto nUnl = validators->getNegativeUNL();
1920 BEAST_EXPECT(nUnl.size() == 12);
1924 for (
int i = 0; i < 6; ++i)
1926 Slice s(data.data(), ss);
1930 validators->setNegativeUNL(nUnl);
1931 validators->updateTrusted(
1937 BEAST_EXPECT(validators->quorum() == 39);
1946 auto validators = createValidatorList(60, 30);
1947 BEAST_EXPECT(validators);
1952 auto it = unl.
begin();
1958 validators->updateTrusted(
1964 BEAST_EXPECT(validators->quorum() == 30);
1972 validators->setNegativeUNL(nUnl);
1973 validators->updateTrusted(
1979 BEAST_EXPECT(validators->quorum() == 30);
1987 testcase(
"Sha512 hashing");
1992 std::string const blob =
"This is not really a blob";
1993 std::string const signature =
"This is not really a signature";
1997 BEAST_EXPECT(!!global);
2000 blobVector[0].blob = blob;
2001 blobVector[0].signature = signature;
2003 BEAST_EXPECT(global !=
sha512Half(signature, blobVector, version));
2007 {99, blobVector[0]}};
2009 BEAST_EXPECT(global !=
sha512Half(blob, blobMap, version));
2013 protocol::TMValidatorList msg1;
2015 msg1.set_blob(blob);
2016 msg1.set_signature(signature);
2017 msg1.set_version(version);
2019 msg1.set_signature(blob);
2024 protocol::TMValidatorListCollection msg2;
2026 msg2.set_version(version);
2027 auto& bi = *msg2.add_blobs();
2029 bi.set_signature(signature);
2039 testcase(
"Build and split messages");
2042 auto extractHeader = [
this](
Message& message) {
2043 auto const& buffer =
2044 message.getBuffer(compression::Compressed::Off);
2046 boost::beast::multi_buffer buffers;
2049 auto start = buffer.begin();
2050 auto end = buffer.end();
2052 buffers.commit(boost::asio::buffer_copy(
2053 buffers.prepare(slice.
size()), boost::asio::buffer(slice)));
2055 boost::system::error_code ec;
2057 detail::parseMessageHeader(ec, buffers.data(), buffers.size());
2061 auto extractProtocolMessage1 = [
this,
2062 &extractHeader](
Message& message) {
2063 auto [header, buffers] = extractHeader(message);
2064 if (BEAST_EXPECT(header) &&
2065 BEAST_EXPECT(header->message_type == protocol::mtVALIDATORLIST))
2068 detail::parseMessageContent<protocol::TMValidatorList>(
2069 *header, buffers.data());
2075 auto extractProtocolMessage2 = [
this,
2076 &extractHeader](
Message& message) {
2077 auto [header, buffers] = extractHeader(message);
2078 if (BEAST_EXPECT(header) &&
2080 header->message_type ==
2081 protocol::mtVALIDATORLISTCOLLECTION))
2083 auto const msg = detail::parseMessageContent<
2084 protocol::TMValidatorListCollection>(
2085 *header, buffers.data());
2091 auto verifyMessage =
2094 &extractProtocolMessage1,
2095 &extractProtocolMessage2](
2098 auto const& blobInfos,
2099 auto const& messages,
2102 BEAST_EXPECT(messages.size() == expectedInfo.size());
2103 auto msgIter = expectedInfo.begin();
2104 for (
auto const& messageWithHash : messages)
2106 if (!BEAST_EXPECT(msgIter != expectedInfo.end()))
2108 if (!BEAST_EXPECT(messageWithHash.message))
2110 auto const& expectedSeqs = msgIter->second;
2111 auto seqIter = expectedSeqs.begin();
2113 messageWithHash.message
2114 ->getBuffer(compression::Compressed::Off)
2117 BEAST_EXPECT(size == msgIter->first);
2118 if (expectedSeqs.size() == 1)
2121 extractProtocolMessage1(*messageWithHash.message);
2122 auto const expectedVersion = 1;
2123 if (BEAST_EXPECT(msg))
2125 BEAST_EXPECT(msg->version() == expectedVersion);
2126 if (!BEAST_EXPECT(seqIter != expectedSeqs.end()))
2128 auto const& expectedBlob = blobInfos.at(*seqIter);
2130 (*seqIter < manifestCutoff) ==
2131 !!expectedBlob.manifest);
2132 auto const expectedManifest =
2133 *seqIter < manifestCutoff &&
2134 expectedBlob.manifest
2135 ? *expectedBlob.manifest
2137 BEAST_EXPECT(msg->manifest() == expectedManifest);
2138 BEAST_EXPECT(msg->blob() == expectedBlob.blob);
2140 msg->signature() == expectedBlob.signature);
2142 BEAST_EXPECT(seqIter == expectedSeqs.end());
2145 messageWithHash.hash ==
2149 expectedBlob.signature,
2156 hashingBlobs.
reserve(msgIter->second.size());
2159 extractProtocolMessage2(*messageWithHash.message);
2160 if (BEAST_EXPECT(msg))
2162 BEAST_EXPECT(msg->version() == version);
2163 BEAST_EXPECT(msg->manifest() ==
manifest);
2164 for (
auto const& blobInfo : msg->blobs())
2167 seqIter != expectedSeqs.end()))
2169 auto const& expectedBlob =
2170 blobInfos.at(*seqIter);
2173 blobInfo.has_manifest() ==
2174 !!expectedBlob.manifest);
2176 blobInfo.has_manifest() ==
2177 (*seqIter < manifestCutoff));
2179 if (*seqIter < manifestCutoff)
2181 blobInfo.manifest() ==
2182 *expectedBlob.manifest);
2184 blobInfo.blob() == expectedBlob.blob);
2186 blobInfo.signature() ==
2187 expectedBlob.signature);
2190 BEAST_EXPECT(seqIter == expectedSeqs.end());
2193 messageWithHash.hash ==
2198 BEAST_EXPECT(msgIter == expectedInfo.end());
2200 auto verifyBuildMessages =
2205 BEAST_EXPECT(result.
first == expectedSequence);
2206 BEAST_EXPECT(result.
second == expectedSize);
2212 auto const blobInfos = [manifestCutoff = manifestCutoff]() {
2215 for (
auto seq : {5, 6, 7, 10, 12})
2219 s <<
"This is not a blob with sequence " <<
seq;
2222 s <<
"This is not a signature for sequence " <<
seq;
2223 b.signature = s.
str();
2224 if (
seq < manifestCutoff)
2228 s <<
"This is not manifest " <<
seq;
2229 b.manifest = s.
str();
2234 auto const maxSequence = blobInfos.
rbegin()->first;
2235 BEAST_EXPECT(maxSequence == 12);
2242 verifyBuildMessages(
2243 ValidatorList::buildValidatorListMessages(
2244 1, 8, maxSequence, version,
manifest, blobInfos, messages),
2247 BEAST_EXPECT(messages.size() == 0);
2253 messages.emplace_back();
2254 verifyBuildMessages(
2255 ValidatorList::buildValidatorListMessages(
2256 1, 3, maxSequence, version,
manifest, blobInfos, messages),
2259 BEAST_EXPECT(messages.size() == 1 && !messages.front().message);
2263 verifyBuildMessages(
2264 ValidatorList::buildValidatorListMessages(
2265 1, 3, maxSequence, version,
manifest, blobInfos, messages),
2268 if (BEAST_EXPECT(messages.size() == 1) &&
2269 BEAST_EXPECT(messages.front().message))
2271 auto const& messageWithHash = messages.front();
2272 auto const msg = extractProtocolMessage1(*messageWithHash.message);
2274 messageWithHash.message->getBuffer(compression::Compressed::Off)
2277 BEAST_EXPECT(size == 108);
2278 auto const& expected = blobInfos.at(5);
2279 if (BEAST_EXPECT(msg))
2281 BEAST_EXPECT(msg->version() == 1);
2282 BEAST_EXPECT(msg->manifest() == *expected.manifest);
2283 BEAST_EXPECT(msg->blob() == expected.blob);
2284 BEAST_EXPECT(msg->signature() == expected.signature);
2287 messageWithHash.hash ==
2289 *expected.manifest, expected.blob, expected.signature, 1));
2297 verifyBuildMessages(
2298 ValidatorList::buildValidatorListMessages(
2308 BEAST_EXPECT(messages.size() == 0);
2314 messages.emplace_back();
2315 verifyBuildMessages(
2316 ValidatorList::buildValidatorListMessages(
2317 2, 3, maxSequence, version,
manifest, blobInfos, messages),
2320 BEAST_EXPECT(messages.size() == 1 && !messages.front().message);
2324 verifyBuildMessages(
2325 ValidatorList::buildValidatorListMessages(
2326 2, 5, maxSequence, version,
manifest, blobInfos, messages),
2330 version,
manifest, blobInfos, messages, {{372, {6, 7, 10, 12}}});
2336 verifyBuildMessages(
2337 ValidatorList::buildValidatorListMessages(
2338 2, 5, maxSequence, version,
manifest, blobInfos, messages, 300),
2346 {{212, {6, 7}}, {192, {10, 12}}});
2351 verifyBuildMessages(
2352 ValidatorList::buildValidatorListMessages(
2353 2, 5, maxSequence, version,
manifest, blobInfos, messages, 200),
2361 {{108, {6}}, {108, {7}}, {192, {10, 12}}});
2365 verifyBuildMessages(
2366 ValidatorList::buildValidatorListMessages(
2367 2, 5, maxSequence, version,
manifest, blobInfos, messages, 150),
2375 {{108, {6}}, {108, {7}}, {110, {10}}, {110, {12}}});
2380 verifyBuildMessages(
2381 ValidatorList::buildValidatorListMessages(
2382 2, 5, maxSequence, version,
manifest, blobInfos, messages, 108),
2390 {{108, {6}}, {108, {7}}, {110, {10}}, {110, {12}}});
2397 testGenesisQuorum();
2401 testUpdateTrusted();
2405 testBuildMessages();
testcase_t testcase
Memberspace for declaring test cases.
virtual Config & config()=0
virtual Overlay & overlay()=0
virtual TimeKeeper & timeKeeper()=0
virtual NetworkOPs & getOPs()=0
virtual HashRouter & getHashRouter()=0
void legacy(std::string const §ion, std::string value)
Set a value that is not a key/value pair.
Remembers manifests with the highest sequence number.
std::optional< PublicKey > getSigningKey(PublicKey const &pk) const
Returns master key's current signing key.
bool revoked(PublicKey const &pk) const
Returns true if master key has been revoked in a manifest.
ManifestDisposition applyManifest(Manifest m)
Add manifest to cache.
void add(Serializer &s) const override
std::size_t size() const noexcept
void const * data() const noexcept
An immutable linear range of bytes.
time_point now() const override
Returns the current time.
void run() override
Runs the suite.
static PublicKey randomMasterKey()
static hash_set< NodeID > asNodeIDs(std::initializer_list< PublicKey > const &pks)
void checkResult(ValidatorList::PublisherListStats const &result, PublicKey pubKey, ListDisposition expectedWorst, ListDisposition expectedBest)
static std::string makeRevocationString(PublicKey const &pk, SecretKey const &sk)
std::string makeList(std::vector< Validator > const &validators, std::size_t sequence, std::size_t validUntil, std::optional< std::size_t > validFrom={})
static std::string makeManifestString(PublicKey const &pk, SecretKey const &sk, PublicKey const &spk, SecretKey const &ssk, int seq)
static PublicKey randomNode()
std::string signList(std::string const &blob, std::pair< PublicKey, SecretKey > const &keys)
static Validator randomValidator()
A transaction testing environment.
beast::Journal const journal
ManualTimeKeeper & timeKeeper()
Set the regular signature on a JTx.
std::unique_ptr< Config > envconfig()
creates and initializes a default configuration for jtx::Env
void sign(Json::Value &jv, Account const &account)
Sign automatically.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
std::optional< Manifest > deserializeManifest(Slice s, beast::Journal journal)
Constructs Manifest from serialized string.
std::string base64_decode(std::string_view data)
@ same_sequence
Same sequence as current list.
@ expired
List is expired, but has the largest non-pending sequence seen so far.
PublicKey derivePublicKey(KeyType type, SecretKey const &sk)
Derive the public key from a secret key.
std::optional< KeyType > publicKeyType(Slice const &slice)
Returns the type of public key.
std::string strHex(FwdIt begin, FwdIt end)
std::enable_if_t< std::is_same< T, char >::value||std::is_same< T, unsigned char >::value, Slice > makeSlice(std::array< T, N > const &a)
SecretKey randomSecretKey()
Create a secret key using secure random numbers.
std::string base64_encode(std::uint8_t const *data, std::size_t len)
NodeID calcNodeID(PublicKey const &)
Calculate the 160-bit node ID from a node public key.
std::pair< PublicKey, SecretKey > randomKeyPair(KeyType type)
Create a key pair using secure random numbers.
sha512_half_hasher::result_type sha512Half(Args const &... args)
Returns the SHA512-Half of a series of objects.
Changes in trusted nodes after updating validator list.
hash_set< NodeID > removed
Describes the result of processing a Validator List (UNL), including some of the information from the...
ListDisposition bestDisposition() const
ListDisposition worstDisposition() const
std::optional< PublicKey > publisherKey
Set the sequence number on a JTx.
T time_since_epoch(T... args)