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/STValidation.h>
30 #include <ripple/protocol/digest.h>
31 #include <ripple/protocol/jss.h>
32 #include <ripple/protocol/messages.h>
33 #include <boost/regex.hpp>
52 return "same_sequence";
56 return "known_sequence";
58 return "unsupported_version";
79 : publisherKey(key), status(stat), sequence(seq)
88 : dispositions.begin()->first;
95 : dispositions.rbegin()->first;
104 dispositions[disp] +=
count;
112 : message(message_), hash(hash_), numVLs(num_)
130 ,
quorum_(minimumQuorum.value_or(1))
141 static boost::regex
const re(
156 <<
"Loading configured trusted validator list publisher keys";
159 for (
auto key : publisherKeys)
161 JLOG(
j_.
trace()) <<
"Processing '" << key <<
"'";
167 JLOG(
j_.
error()) <<
"Invalid validator list publisher key: " << key;
177 <<
"Configured validator list publisher key is revoked: "
185 <<
"Duplicate validator list publisher key: " << key;
201 JLOG(
j_.
debug()) <<
"Loading configured validator keys";
204 for (
auto const& n : configKeys)
206 JLOG(
j_.
trace()) <<
"Processing '" << n <<
"'";
210 if (!boost::regex_match(n, match, re))
212 JLOG(
j_.
error()) <<
"Malformed entry: '" << n <<
"'";
220 JLOG(
j_.
error()) <<
"Invalid node identity: " << match[1];
231 JLOG(
j_.
warn()) <<
"Duplicate node identity: " << match[1];
236 auto&
current = it->second.current;
238 current.validUntil = TimeKeeper::time_point::max();
239 current.list.emplace_back(*
id);
249 boost::filesystem::path
278 auto const effectiveVersion =
279 forceVersion ? *forceVersion : pubCollection.
rawVersion;
282 value[jss::version] = effectiveVersion;
283 value[jss::public_key] = pubKey;
285 switch (effectiveVersion)
289 value[jss::blob] =
current.rawBlob;
290 value[jss::signature] =
current.rawSignature;
295 value[jss::manifest] = *
current.rawManifest;
301 auto add = [&blobs, &outerManifest = pubCollection.
rawManifest](
304 blob[jss::blob] = pubList.rawBlob;
305 blob[jss::signature] = pubList.rawSignature;
306 if (pubList.rawManifest &&
307 *pubList.rawManifest != outerManifest)
308 blob[jss::manifest] = *pubList.rawManifest;
318 value[jss::blobs_v2] = std::move(blobs);
323 <<
"Invalid VL version provided: " << effectiveVersion;
340 boost::system::error_code ec;
348 value[jss::refresh_interval] = 24 * 60;
355 JLOG(
j_.
error()) <<
"Problem writing " << filename <<
" " << ec.value()
356 <<
": " << ec.message();
377 assert(result.
size() == 1);
386 if (!body.
isMember(jss::blobs_v2) ||
387 !body[jss::blobs_v2].
isArray() ||
392 auto const& blobs = body[jss::blobs_v2];
394 for (
auto const& blobInfo : blobs)
396 if (!blobInfo.isObject() ||
397 !blobInfo.isMember(jss::signature) ||
398 !blobInfo[jss::signature].isString() ||
399 !blobInfo.isMember(jss::blob) ||
400 !blobInfo[jss::blob].isString())
403 info.
blob = blobInfo[jss::blob].asString();
404 info.
signature = blobInfo[jss::signature].asString();
405 if (blobInfo.isMember(jss::manifest))
407 if (!blobInfo[jss::manifest].isString())
409 info.
manifest = blobInfo[jss::manifest].asString();
412 assert(result.
size() == blobs.size());
422 return {{body.blob(), body.signature(), {}}};
432 result.
reserve(body.blobs_size());
433 for (
auto const& blob : body.blobs())
436 info.
blob = blob.blob();
438 if (blob.has_manifest())
443 assert(result.
size() == body.blobs_size());
450 protocol::TMValidatorListCollection
const& largeMsg,
458 protocol::TMValidatorListCollection
const& largeMsg,
463 if (begin == 0 && end == 0)
464 end = largeMsg.blobs_size();
469 auto mid = (begin + end) / 2;
479 protocol::TMValidatorListCollection
const& largeMsg,
486 if (end - begin == 1)
488 protocol::TMValidatorList smallMsg;
489 smallMsg.set_version(1);
490 smallMsg.set_manifest(largeMsg.manifest());
492 auto const& blob = largeMsg.blobs(begin);
493 smallMsg.set_blob(blob.blob());
494 smallMsg.set_signature(blob.signature());
496 if (blob.has_manifest())
497 smallMsg.set_manifest(blob.manifest());
502 std::make_shared<Message>(smallMsg, protocol::mtVALIDATORLIST),
511 smallMsg->set_version(largeMsg.version());
512 smallMsg->set_manifest(largeMsg.manifest());
516 *smallMsg->add_blobs() = largeMsg.blobs(i);
523 return splitMessage(messages, largeMsg, maxSize, begin, end);
528 std::make_shared<Message>(
529 *smallMsg, protocol::mtVALIDATORLISTCOLLECTION),
531 smallMsg->blobs_size());
547 assert(messages.
empty());
548 protocol::TMValidatorList msg;
551 auto const version = 1;
553 msg.set_blob(currentBlob.
blob);
554 msg.set_signature(currentBlob.
signature);
556 msg.set_version(version);
560 std::make_shared<Message>(msg, protocol::mtVALIDATORLIST),
577 assert(messages.
empty());
578 protocol::TMValidatorListCollection msg;
579 auto const version = rawVersion < 2 ? 2 : rawVersion;
580 msg.set_version(version);
581 msg.set_manifest(rawManifest);
583 for (
auto const& [sequence, blobInfo] : blobInfos)
585 if (sequence <= peerSequence)
587 protocol::ValidatorBlobInfo& blob = *msg.add_blobs();
588 blob.set_blob(blobInfo.blob);
589 blob.set_signature(blobInfo.signature);
590 if (blobInfo.manifest)
591 blob.set_manifest(*blobInfo.manifest);
593 assert(msg.blobs_size() > 0);
602 std::make_shared<Message>(msg, protocol::mtVALIDATORLISTCOLLECTION),
622 assert(!blobInfos.
empty());
623 auto const& [currentSeq, currentBlob] = *blobInfos.
begin();
629 return total + m.numVLs;
631 if (messageVersion == 2 && peerSequence < maxSequence)
634 if (messages.
empty())
643 if (messages.
empty())
650 return {maxSequence, numVLs};
652 else if (messageVersion == 1 && peerSequence < currentSeq)
655 if (messages.
empty())
660 currentBlob.manifest ? *currentBlob.manifest : rawManifest,
663 if (messages.
empty())
670 return {currentSeq, numVLs};
706 assert(!messages.
empty());
711 for (
auto const& message : messages)
715 peer.
send(message.message);
722 assert(sent || messages.size() == 1);
725 if (messageVersion > 1)
727 <<
"Sent " << messages.size()
728 <<
" validator list collection(s) containing " << numVLs
729 <<
" validator list(s) for " <<
strHex(publisherKey)
730 <<
" with sequence range " << peerSequence <<
", "
731 << newPeerSequence <<
" to "
738 <<
"Sent validator list for " <<
strHex(publisherKey)
739 <<
" with sequence " << newPeerSequence <<
" to "
782 blobInfos[
current.sequence] = {
784 for (
auto const& [sequence, vl] : remaining)
786 blobInfos[sequence] = {vl.rawBlob, vl.rawSignature, vl.rawManifest};
833 lists.
remaining.count(maxSequence) == 1);
838 if (toSkip->count(peer->id()) == 0)
840 auto const peerSequence =
841 peer->publisherListSequence(publisherKey).value_or(0);
842 if (peerSequence < maxSequence)
844 if (blobInfos.
empty())
846 auto const v2 = peer->supportsFeature(
856 v2 ? messages2[peerSequence] : messages1,
881 auto const disposition = result.bestDisposition();
907 pubCollection.maxSequence);
909 *result.publisherKey,
911 *pubCollection.maxSequence,
938 for (
auto const& blobInfo : blobs)
954 stats.mergeDispositions(result);
955 result = std::move(stats);
967 auto& remaining = pubCollection.remaining;
968 auto const&
current = pubCollection.current;
969 for (
auto iter = remaining.begin(); iter != remaining.end();)
972 assert(next == remaining.end() || next->first > iter->first);
973 if (iter->first <=
current.sequence ||
974 (next != remaining.end() &&
975 next->second.validFrom <= iter->second.validFrom))
977 iter = remaining.erase(iter);
987 pubCollection.fullHash =
sha512Half(pubCollection);
989 result.
sequence = *pubCollection.maxSequence;
1005 auto iNew = publisherList.
begin();
1006 auto iOld = oldList.
begin();
1007 while (iNew != publisherList.
end() || iOld != oldList.
end())
1009 if (iOld == oldList.
end() ||
1010 (iNew != publisherList.
end() && *iNew < *iOld))
1017 iNew == publisherList.
end() ||
1018 (iOld != oldList.
end() && *iOld < *iNew))
1034 if (publisherList.
empty())
1036 JLOG(
j_.
warn()) <<
"No validator keys included in valid list";
1039 for (
auto const& valManifest : manifests)
1046 <<
" contained untrusted validator manifest";
1054 <<
" contained invalid validator manifest";
1070 using namespace std::string_literals;
1074 auto const&
manifest = localManifest ? *localManifest : globalManifest;
1075 auto const result =
verify(lock, list, pubKey,
manifest, blob, signature);
1081 if (pubCollection.maxSequence &&
1090 pubCollection.status,
1091 *pubCollection.maxSequence};
1099 auto const sequence = list[jss::sequence].
asUInt();
1108 pubCollection.rawManifest = globalManifest;
1109 if (!pubCollection.maxSequence || sequence > *pubCollection.maxSequence)
1110 pubCollection.maxSequence = sequence;
1112 Json::Value const& newList = list[jss::validators];
1114 if (
accepted && pubCollection.remaining.count(sequence) != 0)
1121 auto& publisher = pubCollection.current;
1123 oldList = std::move(pubCollection.current.list);
1125 publisher = std::move(pubCollection.remaining[sequence]);
1127 pubCollection.remaining.erase(sequence);
1129 assert(publisher.sequence == sequence);
1133 auto& publisher =
accepted ? pubCollection.current
1134 : pubCollection.remaining[sequence];
1135 publisher.sequence = sequence;
1137 list.
isMember(jss::effective) ? list[jss::effective].
asUInt() : 0}};
1140 publisher.siteUri = std::move(siteUri);
1141 publisher.rawBlob = blob;
1142 publisher.rawSignature = signature;
1143 publisher.rawManifest = localManifest;
1145 publisher.hash = *hash;
1151 oldList = std::move(publisherList);
1153 publisherList.
clear();
1155 for (
auto const& val : newList)
1157 if (val.isObject() && val.isMember(jss::validation_public_key) &&
1158 val[jss::validation_public_key].isString())
1161 strUnHex(val[jss::validation_public_key].asString());
1166 <<
"Invalid node identity: "
1167 << val[jss::validation_public_key].asString();
1175 if (val.isMember(jss::manifest) &&
1176 val[jss::manifest].isString())
1177 manifests.
push_back(val[jss::manifest].asString());
1186 pubCollection.rawVersion =
std::max(pubCollection.rawVersion, version);
1187 if (!pubCollection.remaining.empty())
1191 pubCollection.rawVersion =
std::max(pubCollection.rawVersion, 2u);
1195 result, pubKey, pubCollection.status, *pubCollection.maxSequence};
1208 using namespace std::string_literals;
1209 using namespace boost::filesystem;
1210 using namespace boost::system::errc;
1218 boost::system::error_code ec;
1225 auto const fullPath{canonical(filename, ec)};
1229 auto size = file_size(fullPath, ec);
1234 ec = make_error_code(no_such_file_or_directory);
1240 #if _MSC_VER // MSVC: Windows paths need a leading / added
1242 return fullPath.root_path() ==
"/"s ?
"file://" :
"file:///";
1272 pubKey = m->masterKey;
1273 auto const revoked = m->revoked();
1287 auto const sig =
strUnHex(signature);
1297 if (!r.
parse(data, list))
1300 if (list.
isMember(jss::sequence) && list[jss::sequence].
isInt() &&
1301 list.
isMember(jss::expiration) && list[jss::expiration].
isInt() &&
1302 (!list.
isMember(jss::effective) || list[jss::effective].
isInt()) &&
1305 auto const sequence = list[jss::sequence].
asUInt();
1307 list.
isMember(jss::effective) ? list[jss::effective].
asUInt() : 0}};
1312 if (validUntil <= validFrom)
1314 else if (sequence < listCollection.current.sequence)
1316 else if (sequence == listCollection.current.sequence)
1318 else if (validUntil <= now)
1320 else if (validFrom > now)
1331 return !listCollection.maxSequence ||
1332 sequence > *listCollection.maxSequence ||
1333 (listCollection.remaining.count(sequence) == 0 &&
1334 validFrom < listCollection.remaining
1335 .at(*listCollection.maxSequence)
1370 return trusted(read_lock, identity);
1381 return std::nullopt;
1392 return std::nullopt;
1431 JLOG(
j_.
debug()) <<
"Removing validator list for publisher "
1434 for (
auto const& val : iList->second.current.list)
1440 if (iVal->second <= 1)
1446 iList->second.current.list.clear();
1447 iList->second.status = reason;
1462 return count(read_lock);
1473 auto const&
current = collection.current;
1475 return std::nullopt;
1480 auto chainedExpiration =
current.validUntil;
1481 for (
auto const& [sequence, check] : collection.remaining)
1484 if (check.validFrom <= chainedExpiration)
1485 chainedExpiration = check.validUntil;
1491 if (!res || chainedExpiration < *res)
1493 res = chainedExpiration;
1520 if (
auto when =
expires(read_lock))
1522 if (*when == TimeKeeper::time_point::max())
1524 x[jss::expiration] =
"never";
1525 x[jss::status] =
"active";
1532 x[jss::status] =
"active";
1534 x[jss::status] =
"expired";
1539 x[jss::status] =
"unknown";
1540 x[jss::expiration] =
"unknown";
1550 for (
auto const& key : it->second.current.list)
1559 if (local == publicKey)
1562 curr[jss::pubkey_publisher] =
strHex(publicKey);
1563 curr[jss::available] =
1568 target[jss::uri] = publisherList.
siteUri;
1578 for (
auto const& key : publisherList.
list)
1584 auto const&
current = pubCollection.current;
1588 curr[jss::version] = pubCollection.rawVersion;
1593 for (
auto const& [sequence, future] : pubCollection.remaining)
1595 using namespace std::chrono_literals;
1599 appendList(future, r);
1603 if (remaining.
size())
1604 curr[jss::remaining] = std::move(remaining);
1618 this](Manifest
const& manifest) {
1647 func(v.first,
trusted(read_lock, v.first));
1658 uint256 const& hash)> func)
const
1666 assert(plCollection.maxSequence);
1668 plCollection.rawManifest,
1669 plCollection.rawVersion,
1672 plCollection.maxSequence.value_or(0),
1673 plCollection.fullHash);
1679 boost::beast::string_view
const& pubKey,
1688 JLOG(
j_.
info()) <<
"Invalid requested validator list publisher key: "
1716 JLOG(
j_.
warn()) <<
"Using potentially unsafe quorum of "
1718 <<
" as specified on the command line";
1776 using namespace std::chrono_literals;
1787 auto& remaining = collection.remaining;
1788 auto const firstIter = remaining.begin();
1789 auto iter = firstIter;
1790 if (iter != remaining.end() && iter->second.validFrom <= closeTime)
1793 for (
auto next =
std::next(iter); next != remaining.end() &&
1794 next->second.validFrom <= closeTime;
1799 assert(iter != remaining.end());
1802 auto sequence = iter->first;
1803 auto& candidate = iter->second;
1804 auto&
current = collection.current;
1805 assert(candidate.validFrom <= closeTime);
1807 auto const oldList =
current.list;
1808 current = std::move(candidate);
1811 assert(
current.sequence == sequence);
1815 if (
current.validUntil <= closeTime)
1835 remaining.erase(firstIter,
std::next(iter));
1840 collection.current.validUntil <= closeTime)
1876 if (!trustChanges.
added.empty() || !trustChanges.
removed.empty())
1886 <<
" listed validators eligible for inclusion in the trusted set";
1889 auto effectiveUnlSize = unlSize;
1890 auto seenSize = seenValidators.
size();
1903 for (
auto const& nid : seenValidators)
1905 if (negUnlNodeIDs.
count(nid))
1911 JLOG(
j_.
debug()) <<
"Using quorum of " <<
quorum_ <<
" for new set of "
1912 << unlSize <<
" trusted validators ("
1913 << trustChanges.
added.size() <<
" added, "
1914 << trustChanges.
removed.size() <<
" removed)";
1919 <<
" exceeds the number of trusted validators ("
1929 return trustChanges;
1958 auto ret = std::move(validations);
1967 [&](
auto const& v) ->
bool {
1968 if (auto const masterKey =
1969 getTrustedKey(read_lock, v->getSignerPublic());
1972 return negativeUNL_.count(*masterKey);