20 #include <ripple/app/misc/HashRouter.h>
21 #include <ripple/app/misc/NetworkOPs.h>
22 #include <ripple/app/misc/ValidatorList.h>
23 #include <ripple/basics/FileUtilities.h>
24 #include <ripple/basics/Slice.h>
25 #include <ripple/basics/StringUtilities.h>
26 #include <ripple/basics/base64.h>
27 #include <ripple/json/json_reader.h>
28 #include <ripple/overlay/Overlay.h>
29 #include <ripple/protocol/PublicKey.h>
30 #include <ripple/protocol/STValidation.h>
31 #include <ripple/protocol/digest.h>
32 #include <ripple/protocol/jss.h>
33 #include <ripple/protocol/messages.h>
34 #include <boost/regex.hpp>
53 return "same_sequence";
57 return "known_sequence";
59 return "unsupported_version";
80 : publisherKey(key), status(stat), sequence(seq)
89 : dispositions.begin()->first;
96 : dispositions.rbegin()->first;
105 dispositions[disp] +=
count;
113 : message(message_), hash(hash_), numVLs(num_)
131 ,
quorum_(minimumQuorum.value_or(1))
142 static boost::regex
const re(
157 <<
"Loading configured trusted validator list publisher keys";
160 for (
auto key : publisherKeys)
162 JLOG(
j_.
trace()) <<
"Processing '" << key <<
"'";
168 JLOG(
j_.
error()) <<
"Invalid validator list publisher key: " << key;
178 <<
"Configured validator list publisher key is revoked: "
186 <<
"Duplicate validator list publisher key: " << key;
203 JLOG(
j_.
debug()) <<
"Loading configured validator keys";
206 for (
auto const& n : configKeys)
208 JLOG(
j_.
trace()) <<
"Processing '" << n <<
"'";
212 if (!boost::regex_match(n, match, re))
214 JLOG(
j_.
error()) <<
"Malformed entry: '" << n <<
"'";
222 JLOG(
j_.
error()) <<
"Invalid node identity: " << match[1];
233 JLOG(
j_.
warn()) <<
"Duplicate node identity: " << match[1];
251 boost::filesystem::path
280 auto const effectiveVersion =
281 forceVersion ? *forceVersion : pubCollection.
rawVersion;
284 value[jss::version] = effectiveVersion;
285 value[jss::public_key] = pubKey;
287 switch (effectiveVersion)
291 value[jss::blob] =
current.rawBlob;
292 value[jss::signature] =
current.rawSignature;
297 value[jss::manifest] = *
current.rawManifest;
303 auto add = [&blobs, &outerManifest = pubCollection.
rawManifest](
306 blob[jss::blob] = pubList.rawBlob;
307 blob[jss::signature] = pubList.rawSignature;
308 if (pubList.rawManifest &&
309 *pubList.rawManifest != outerManifest)
310 blob[jss::manifest] = *pubList.rawManifest;
320 value[jss::blobs_v2] = std::move(blobs);
325 <<
"Invalid VL version provided: " << effectiveVersion;
342 boost::system::error_code ec;
350 value[jss::refresh_interval] = 24 * 60;
357 JLOG(
j_.
error()) <<
"Problem writing " << filename <<
" " << ec.value()
358 <<
": " << ec.message();
379 assert(result.
size() == 1);
388 if (!body.
isMember(jss::blobs_v2) ||
389 !body[jss::blobs_v2].
isArray() ||
394 auto const& blobs = body[jss::blobs_v2];
396 for (
auto const& blobInfo : blobs)
398 if (!blobInfo.isObject() ||
399 !blobInfo.isMember(jss::signature) ||
400 !blobInfo[jss::signature].isString() ||
401 !blobInfo.isMember(jss::blob) ||
402 !blobInfo[jss::blob].isString())
405 info.
blob = blobInfo[jss::blob].asString();
406 info.
signature = blobInfo[jss::signature].asString();
407 if (blobInfo.isMember(jss::manifest))
409 if (!blobInfo[jss::manifest].isString())
411 info.
manifest = blobInfo[jss::manifest].asString();
414 assert(result.
size() == blobs.size());
424 return {{body.blob(), body.signature(), {}}};
434 result.
reserve(body.blobs_size());
435 for (
auto const& blob : body.blobs())
438 info.
blob = blob.blob();
440 if (blob.has_manifest())
445 assert(result.
size() == body.blobs_size());
452 protocol::TMValidatorListCollection
const& largeMsg,
460 protocol::TMValidatorListCollection
const& largeMsg,
465 if (begin == 0 && end == 0)
466 end = largeMsg.blobs_size();
471 auto mid = (begin + end) / 2;
481 protocol::TMValidatorListCollection
const& largeMsg,
488 if (end - begin == 1)
490 protocol::TMValidatorList smallMsg;
491 smallMsg.set_version(1);
492 smallMsg.set_manifest(largeMsg.manifest());
494 auto const& blob = largeMsg.blobs(begin);
495 smallMsg.set_blob(blob.blob());
496 smallMsg.set_signature(blob.signature());
498 if (blob.has_manifest())
499 smallMsg.set_manifest(blob.manifest());
504 std::make_shared<Message>(smallMsg, protocol::mtVALIDATORLIST),
513 smallMsg->set_version(largeMsg.version());
514 smallMsg->set_manifest(largeMsg.manifest());
518 *smallMsg->add_blobs() = largeMsg.blobs(i);
525 return splitMessage(messages, largeMsg, maxSize, begin, end);
530 std::make_shared<Message>(
531 *smallMsg, protocol::mtVALIDATORLISTCOLLECTION),
533 smallMsg->blobs_size());
549 assert(messages.
empty());
550 protocol::TMValidatorList msg;
553 auto const version = 1;
555 msg.set_blob(currentBlob.
blob);
556 msg.set_signature(currentBlob.
signature);
558 msg.set_version(version);
562 std::make_shared<Message>(msg, protocol::mtVALIDATORLIST),
579 assert(messages.
empty());
580 protocol::TMValidatorListCollection msg;
581 auto const version = rawVersion < 2 ? 2 : rawVersion;
582 msg.set_version(version);
583 msg.set_manifest(rawManifest);
585 for (
auto const& [sequence, blobInfo] : blobInfos)
587 if (sequence <= peerSequence)
589 protocol::ValidatorBlobInfo& blob = *msg.add_blobs();
590 blob.set_blob(blobInfo.blob);
591 blob.set_signature(blobInfo.signature);
592 if (blobInfo.manifest)
593 blob.set_manifest(*blobInfo.manifest);
595 assert(msg.blobs_size() > 0);
604 std::make_shared<Message>(msg, protocol::mtVALIDATORLISTCOLLECTION),
624 assert(!blobInfos.
empty());
625 auto const& [currentSeq, currentBlob] = *blobInfos.
begin();
631 return total + m.numVLs;
633 if (messageVersion == 2 && peerSequence < maxSequence)
636 if (messages.
empty())
645 if (messages.
empty())
652 return {maxSequence, numVLs};
654 else if (messageVersion == 1 && peerSequence < currentSeq)
657 if (messages.
empty())
662 currentBlob.manifest ? *currentBlob.manifest : rawManifest,
665 if (messages.
empty())
672 return {currentSeq, numVLs};
708 assert(!messages.
empty());
713 for (
auto const& message : messages)
717 peer.
send(message.message);
724 assert(sent || messages.size() == 1);
727 if (messageVersion > 1)
729 <<
"Sent " << messages.size()
730 <<
" validator list collection(s) containing " << numVLs
731 <<
" validator list(s) for " <<
strHex(publisherKey)
732 <<
" with sequence range " << peerSequence <<
", "
733 << newPeerSequence <<
" to "
740 <<
"Sent validator list for " <<
strHex(publisherKey)
741 <<
" with sequence " << newPeerSequence <<
" to "
784 blobInfos[
current.sequence] = {
786 for (
auto const& [sequence, vl] : remaining)
788 blobInfos[sequence] = {vl.rawBlob, vl.rawSignature, vl.rawManifest};
835 lists.
remaining.count(maxSequence) == 1);
840 if (toSkip->count(peer->id()) == 0)
842 auto const peerSequence =
843 peer->publisherListSequence(publisherKey).value_or(0);
844 if (peerSequence < maxSequence)
846 if (blobInfos.
empty())
848 auto const v2 = peer->supportsFeature(
858 v2 ? messages2[peerSequence] : messages1,
883 auto const disposition = result.bestDisposition();
910 result.publisherKey &&
916 *result.publisherKey,
918 *pubCollection.maxSequence,
945 for (
auto const& blobInfo : blobs)
961 stats.mergeDispositions(result);
962 result = std::move(stats);
974 auto& remaining = pubCollection.remaining;
975 auto const&
current = pubCollection.current;
976 for (
auto iter = remaining.begin(); iter != remaining.end();)
979 assert(next == remaining.end() || next->first > iter->first);
980 if (iter->first <=
current.sequence ||
981 (next != remaining.end() &&
982 next->second.validFrom <= iter->second.validFrom))
984 iter = remaining.erase(iter);
994 pubCollection.fullHash =
sha512Half(pubCollection);
996 result.
sequence = *pubCollection.maxSequence;
1012 auto iNew = publisherList.
begin();
1013 auto iOld = oldList.
begin();
1014 while (iNew != publisherList.
end() || iOld != oldList.
end())
1016 if (iOld == oldList.
end() ||
1017 (iNew != publisherList.
end() && *iNew < *iOld))
1024 iNew == publisherList.
end() ||
1025 (iOld != oldList.
end() && *iOld < *iNew))
1041 if (publisherList.
empty())
1043 JLOG(
j_.
warn()) <<
"No validator keys included in valid list";
1046 for (
auto const& valManifest : manifests)
1053 <<
" contained untrusted validator manifest";
1061 <<
" contained invalid validator manifest";
1077 using namespace std::string_literals;
1080 auto const&
manifest = localManifest ? *localManifest : globalManifest;
1081 auto [result, pubKeyOpt] =
verify(lock, list,
manifest, blob, signature);
1085 JLOG(
j_.
info()) <<
"ValidatorList::applyList unable to retrieve the "
1086 "master public key from the verify function\n";
1092 JLOG(
j_.
info()) <<
"ValidatorList::applyList Invalid Public Key type"
1093 " retrieved from the verify function\n ";
1103 if (pubCollection.maxSequence &&
1112 pubCollection.status,
1113 *pubCollection.maxSequence};
1121 auto const sequence = list[jss::sequence].
asUInt();
1130 pubCollection.rawManifest = globalManifest;
1131 if (!pubCollection.maxSequence || sequence > *pubCollection.maxSequence)
1132 pubCollection.maxSequence = sequence;
1134 Json::Value const& newList = list[jss::validators];
1136 if (
accepted && pubCollection.remaining.count(sequence) != 0)
1143 auto& publisher = pubCollection.current;
1145 oldList = std::move(pubCollection.current.list);
1147 publisher = std::move(pubCollection.remaining[sequence]);
1149 pubCollection.remaining.erase(sequence);
1151 assert(publisher.sequence == sequence);
1155 auto& publisher =
accepted ? pubCollection.current
1156 : pubCollection.remaining[sequence];
1157 publisher.sequence = sequence;
1159 list.
isMember(jss::effective) ? list[jss::effective].
asUInt() : 0}};
1162 publisher.siteUri = std::move(siteUri);
1163 publisher.rawBlob = blob;
1164 publisher.rawSignature = signature;
1165 publisher.rawManifest = localManifest;
1167 publisher.hash = *hash;
1173 oldList = std::move(publisherList);
1175 publisherList.
clear();
1177 for (
auto const& val : newList)
1179 if (val.isObject() && val.isMember(jss::validation_public_key) &&
1180 val[jss::validation_public_key].isString())
1183 strUnHex(val[jss::validation_public_key].asString());
1188 <<
"Invalid node identity: "
1189 << val[jss::validation_public_key].asString();
1197 if (val.isMember(jss::manifest) &&
1198 val[jss::manifest].isString())
1199 manifests.
push_back(val[jss::manifest].asString());
1208 pubCollection.rawVersion =
std::max(pubCollection.rawVersion, version);
1209 if (!pubCollection.remaining.empty())
1213 pubCollection.rawVersion =
std::max(pubCollection.rawVersion, 2u);
1217 result, pubKey, pubCollection.status, *pubCollection.maxSequence};
1230 using namespace std::string_literals;
1231 using namespace boost::filesystem;
1232 using namespace boost::system::errc;
1240 boost::system::error_code ec;
1247 auto const fullPath{canonical(filename, ec)};
1251 auto size = file_size(fullPath, ec);
1262 #if _MSC_VER // MSVC: Windows paths need a leading / added
1264 return fullPath.root_path() ==
"/"s ?
"file://" :
"file:///";
1296 auto const revoked = m->revoked();
1312 auto const sig =
strUnHex(signature);
1318 if (!r.
parse(data, list))
1321 if (list.
isMember(jss::sequence) && list[jss::sequence].
isInt() &&
1322 list.
isMember(jss::expiration) && list[jss::expiration].
isInt() &&
1323 (!list.
isMember(jss::effective) || list[jss::effective].
isInt()) &&
1326 auto const sequence = list[jss::sequence].
asUInt();
1328 list.
isMember(jss::effective) ? list[jss::effective].
asUInt() : 0}};
1333 if (validUntil <= validFrom)
1335 else if (sequence < listCollection.current.sequence)
1337 else if (sequence == listCollection.current.sequence)
1339 else if (validUntil <= now)
1341 else if (validFrom > now)
1352 return !listCollection.maxSequence ||
1353 sequence > *listCollection.maxSequence ||
1354 (listCollection.remaining.count(sequence) == 0 &&
1355 validFrom < listCollection.remaining
1356 .at(*listCollection.maxSequence)
1391 return trusted(read_lock, identity);
1402 return std::nullopt;
1413 return std::nullopt;
1452 JLOG(
j_.
debug()) <<
"Removing validator list for publisher "
1455 for (
auto const& val : iList->second.current.list)
1461 if (iVal->second <= 1)
1467 iList->second.current.list.clear();
1468 iList->second.status = reason;
1483 return count(read_lock);
1493 auto const&
current = collection.current;
1496 return std::nullopt;
1502 auto chainedExpiration =
current.validUntil;
1503 for (
auto const& [sequence, check] : collection.remaining)
1506 if (check.validFrom <= chainedExpiration)
1507 chainedExpiration = check.validUntil;
1513 if (!res || chainedExpiration < *res)
1515 res = chainedExpiration;
1523 auto const&
current = collection;
1524 auto chainedExpiration =
current.validUntil;
1527 if (!res || chainedExpiration < *res)
1529 res = chainedExpiration;
1556 if (
auto when =
expires(read_lock))
1558 if (*when == TimeKeeper::time_point::max())
1560 x[jss::expiration] =
"never";
1561 x[jss::status] =
"active";
1568 x[jss::status] =
"active";
1570 x[jss::status] =
"expired";
1575 x[jss::status] =
"unknown";
1576 x[jss::expiration] =
"unknown";
1593 curr[jss::pubkey_publisher] =
strHex(publicKey);
1594 curr[jss::available] =
1599 target[jss::uri] = publisherList.
siteUri;
1609 for (
auto const& key : publisherList.
list)
1615 auto const&
current = pubCollection.current;
1619 curr[jss::version] = pubCollection.rawVersion;
1624 for (
auto const& [sequence, future] : pubCollection.remaining)
1626 using namespace std::chrono_literals;
1630 appendList(future, r);
1634 if (remaining.
size())
1635 curr[jss::remaining] = std::move(remaining);
1649 this](Manifest
const& manifest) {
1678 func(v.first,
trusted(read_lock, v.first));
1689 uint256 const& hash)> func)
const
1697 assert(plCollection.maxSequence);
1699 plCollection.rawManifest,
1700 plCollection.rawVersion,
1703 plCollection.maxSequence.value_or(0),
1704 plCollection.fullHash);
1710 boost::beast::string_view
const& pubKey,
1719 JLOG(
j_.
info()) <<
"Invalid requested validator list publisher key: "
1747 JLOG(
j_.
warn()) <<
"Using potentially unsafe quorum of "
1749 <<
" as specified on the command line";
1807 using namespace std::chrono_literals;
1821 auto& remaining = collection.remaining;
1822 auto const firstIter = remaining.begin();
1823 auto iter = firstIter;
1824 if (iter != remaining.end() && iter->second.validFrom <= closeTime)
1827 for (
auto next =
std::next(iter); next != remaining.end() &&
1828 next->second.validFrom <= closeTime;
1833 assert(iter != remaining.end());
1836 auto sequence = iter->first;
1837 auto& candidate = iter->second;
1838 auto&
current = collection.current;
1839 assert(candidate.validFrom <= closeTime);
1841 auto const oldList =
current.list;
1842 current = std::move(candidate);
1845 assert(
current.sequence == sequence);
1849 if (
current.validUntil <= closeTime)
1869 remaining.erase(firstIter,
std::next(iter));
1876 collection.current.validUntil <= closeTime)
1912 if (!trustChanges.
added.empty() || !trustChanges.
removed.empty())
1929 <<
" listed validators eligible for inclusion in the trusted set";
1932 auto effectiveUnlSize = unlSize;
1933 auto seenSize = seenValidators.
size();
1946 for (
auto const& nid : seenValidators)
1948 if (negUnlNodeIDs.
count(nid))
1954 JLOG(
j_.
debug()) <<
"Using quorum of " <<
quorum_ <<
" for new set of "
1955 << unlSize <<
" trusted validators ("
1956 << trustChanges.
added.size() <<
" added, "
1957 << trustChanges.
removed.size() <<
" removed)";
1962 <<
" exceeds the number of trusted validators ("
1973 return trustChanges;
2002 auto ret = std::move(validations);
2011 [&](
auto const& v) ->
bool {
2012 if (auto const masterKey =
2013 getTrustedKey(read_lock, v->getSignerPublic());
2016 return negativeUNL_.count(*masterKey);