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>
35 #include <date/date.h>
54 return "same_sequence";
58 return "known_sequence";
60 return "unsupported_version";
81 : publisherKey(key), status(stat), sequence(seq)
90 : dispositions.begin()->first;
97 : dispositions.rbegin()->first;
106 dispositions[disp] +=
count;
114 : message(message_), hash(hash_), numVLs(num_)
126 boost::optional<std::size_t> minimumQuorum)
132 ,
quorum_(minimumQuorum.value_or(1))
143 static boost::regex
const re(
158 <<
"Loading configured trusted validator list publisher keys";
161 for (
auto key : publisherKeys)
163 JLOG(
j_.
trace()) <<
"Processing '" << key <<
"'";
169 JLOG(
j_.
error()) <<
"Invalid validator list publisher key: " << key;
179 <<
"Configured validator list publisher key is revoked: "
187 <<
"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];
238 auto&
current = it->second.current;
240 current.validUntil = TimeKeeper::time_point::max();
241 current.list.emplace_back(*
id);
251 boost::filesystem::path
274 boost::optional<std::uint32_t> forceVersion,
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),
511 boost::optional<protocol::TMValidatorListCollection> smallMsg;
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();
909 pubCollection.maxSequence);
911 *result.publisherKey,
913 *pubCollection.maxSequence,
929 boost::optional<uint256>
const& hash )
940 for (
auto const& blobInfo : blobs)
956 stats.mergeDispositions(result);
957 result = std::move(stats);
969 auto& remaining = pubCollection.remaining;
970 auto const&
current = pubCollection.current;
971 for (
auto iter = remaining.begin(); iter != remaining.end();)
974 assert(next == remaining.end() || next->first > iter->first);
975 if (iter->first <=
current.sequence ||
976 (next != remaining.end() &&
977 next->second.validFrom <= iter->second.validFrom))
979 iter = remaining.erase(iter);
989 pubCollection.fullHash =
sha512Half(pubCollection);
991 result.
sequence = *pubCollection.maxSequence;
1007 auto iNew = publisherList.
begin();
1008 auto iOld = oldList.
begin();
1009 while (iNew != publisherList.
end() || iOld != oldList.
end())
1011 if (iOld == oldList.
end() ||
1012 (iNew != publisherList.
end() && *iNew < *iOld))
1019 iNew == publisherList.
end() ||
1020 (iOld != oldList.
end() && *iOld < *iNew))
1036 if (publisherList.
empty())
1038 JLOG(
j_.
warn()) <<
"No validator keys included in valid list";
1041 for (
auto const& valManifest : manifests)
1048 <<
" contained untrusted validator manifest";
1056 <<
" contained invalid validator manifest";
1064 boost::optional<std::string>
const& localManifest,
1069 boost::optional<uint256>
const& hash,
1072 using namespace std::string_literals;
1076 auto const&
manifest = localManifest ? *localManifest : globalManifest;
1077 auto const result =
verify(lock, list, pubKey,
manifest, blob, signature);
1083 if (pubCollection.maxSequence &&
1092 pubCollection.status,
1093 *pubCollection.maxSequence};
1101 auto const sequence = list[jss::sequence].
asUInt();
1110 pubCollection.rawManifest = globalManifest;
1111 if (!pubCollection.maxSequence || sequence > *pubCollection.maxSequence)
1112 pubCollection.maxSequence = sequence;
1114 Json::Value const& newList = list[jss::validators];
1116 if (
accepted && pubCollection.remaining.count(sequence) != 0)
1123 auto& publisher = pubCollection.current;
1125 oldList = std::move(pubCollection.current.list);
1127 publisher = std::move(pubCollection.remaining[sequence]);
1129 pubCollection.remaining.erase(sequence);
1131 assert(publisher.sequence == sequence);
1135 auto& publisher =
accepted ? pubCollection.current
1136 : pubCollection.remaining[sequence];
1137 publisher.sequence = sequence;
1139 list.
isMember(jss::effective) ? list[jss::effective].
asUInt() : 0}};
1142 publisher.siteUri = std::move(siteUri);
1143 publisher.rawBlob = blob;
1144 publisher.rawSignature = signature;
1145 publisher.rawManifest = localManifest;
1147 publisher.hash = *hash;
1153 oldList = std::move(publisherList);
1155 publisherList.
clear();
1157 for (
auto const& val : newList)
1159 if (val.isObject() && val.isMember(jss::validation_public_key) &&
1160 val[jss::validation_public_key].isString())
1162 boost::optional<Blob>
const ret =
1163 strUnHex(val[jss::validation_public_key].asString());
1168 <<
"Invalid node identity: "
1169 << val[jss::validation_public_key].asString();
1177 if (val.isMember(jss::manifest) &&
1178 val[jss::manifest].isString())
1179 manifests.
push_back(val[jss::manifest].asString());
1188 pubCollection.rawVersion =
std::max(pubCollection.rawVersion, version);
1189 if (!pubCollection.remaining.empty())
1193 pubCollection.rawVersion =
std::max(pubCollection.rawVersion, 2u);
1197 result, pubKey, pubCollection.status, *pubCollection.maxSequence};
1210 using namespace std::string_literals;
1211 using namespace boost::filesystem;
1212 using namespace boost::system::errc;
1220 boost::system::error_code ec;
1227 auto const fullPath{canonical(filename, ec)};
1231 auto size = file_size(fullPath, ec);
1236 ec = make_error_code(no_such_file_or_directory);
1242 #if _MSC_VER // MSVC: Windows paths need a leading / added
1244 return fullPath.root_path() ==
"/"s ?
"file://" :
"file:///";
1274 pubKey = m->masterKey;
1275 auto const revoked = m->revoked();
1289 auto const sig =
strUnHex(signature);
1299 if (!r.
parse(data, list))
1302 if (list.
isMember(jss::sequence) && list[jss::sequence].
isInt() &&
1303 list.
isMember(jss::expiration) && list[jss::expiration].
isInt() &&
1304 (!list.
isMember(jss::effective) || list[jss::effective].
isInt()) &&
1307 auto const sequence = list[jss::sequence].
asUInt();
1309 list.
isMember(jss::effective) ? list[jss::effective].
asUInt() : 0}};
1314 if (validUntil <= validFrom)
1316 else if (sequence < listCollection.current.sequence)
1318 else if (sequence == listCollection.current.sequence)
1320 else if (validUntil <= now)
1322 else if (validFrom > now)
1333 return !listCollection.maxSequence ||
1334 sequence > *listCollection.maxSequence ||
1335 (listCollection.remaining.count(sequence) == 0 &&
1336 validFrom < listCollection.remaining
1337 .at(*listCollection.maxSequence)
1372 return trusted(read_lock, identity);
1375 boost::optional<PublicKey>
1386 boost::optional<PublicKey>
1397 boost::optional<PublicKey>
1433 JLOG(
j_.
debug()) <<
"Removing validator list for publisher "
1436 for (
auto const& val : iList->second.current.list)
1442 if (iVal->second <= 1)
1448 iList->second.current.list.clear();
1449 iList->second.status = reason;
1464 return count(read_lock);
1467 boost::optional<TimeKeeper::time_point>
1470 boost::optional<TimeKeeper::time_point> res{boost::none};
1475 auto const&
current = collection.current;
1482 auto chainedExpiration =
current.validUntil;
1483 for (
auto const& [sequence, check] : collection.remaining)
1486 if (check.validFrom <= chainedExpiration)
1487 chainedExpiration = check.validUntil;
1493 if (!res || chainedExpiration < *res)
1495 res = chainedExpiration;
1501 boost::optional<TimeKeeper::time_point>
1522 if (
auto when =
expires(read_lock))
1524 if (*when == TimeKeeper::time_point::max())
1526 x[jss::expiration] =
"never";
1527 x[jss::status] =
"active";
1534 x[jss::status] =
"active";
1536 x[jss::status] =
"expired";
1541 x[jss::status] =
"unknown";
1542 x[jss::expiration] =
"unknown";
1552 for (
auto const& key : it->second.current.list)
1561 if (local == publicKey)
1564 curr[jss::pubkey_publisher] =
strHex(publicKey);
1565 curr[jss::available] =
1570 target[jss::uri] = publisherList.
siteUri;
1580 for (
auto const& key : publisherList.
list)
1586 auto const&
current = pubCollection.current;
1590 curr[jss::version] = pubCollection.rawVersion;
1595 for (
auto const& [sequence, future] : pubCollection.remaining)
1597 using namespace std::chrono_literals;
1601 appendList(future, r);
1605 if (remaining.
size())
1606 curr[jss::remaining] = std::move(remaining);
1620 this](Manifest
const& manifest) {
1649 func(v.first,
trusted(read_lock, v.first));
1660 uint256 const& hash)> func)
const
1668 assert(plCollection.maxSequence);
1670 plCollection.rawManifest,
1671 plCollection.rawVersion,
1674 plCollection.maxSequence.value_or(0),
1675 plCollection.fullHash);
1679 boost::optional<Json::Value>
1681 boost::beast::string_view
const& pubKey,
1682 boost::optional<std::uint32_t> forceVersion )
1690 JLOG(
j_.
info()) <<
"Invalid requested validator list publisher key: "
1768 <<
" as specified in the command line";
1782 using namespace std::chrono_literals;
1793 auto& remaining = collection.remaining;
1794 auto const firstIter = remaining.begin();
1795 auto iter = firstIter;
1796 if (iter != remaining.end() && iter->second.validFrom <= closeTime)
1799 for (
auto next =
std::next(iter); next != remaining.end() &&
1800 next->second.validFrom <= closeTime;
1805 assert(iter != remaining.end());
1808 auto sequence = iter->first;
1809 auto& candidate = iter->second;
1810 auto&
current = collection.current;
1811 assert(candidate.validFrom <= closeTime);
1813 auto const oldList =
current.list;
1814 current = std::move(candidate);
1817 assert(
current.sequence == sequence);
1821 if (
current.validUntil <= closeTime)
1841 remaining.erase(firstIter,
std::next(iter));
1846 collection.current.validUntil <= closeTime)
1882 if (!trustChanges.
added.empty() || !trustChanges.
removed.empty())
1892 <<
" listed validators eligible for inclusion in the trusted set";
1895 auto effectiveUnlSize = unlSize;
1896 auto seenSize = seenValidators.
size();
1909 for (
auto const& nid : seenValidators)
1911 if (negUnlNodeIDs.
count(nid))
1917 JLOG(
j_.
debug()) <<
"Using quorum of " <<
quorum_ <<
" for new set of "
1918 << unlSize <<
" trusted validators ("
1919 << trustChanges.
added.size() <<
" added, "
1920 << trustChanges.
removed.size() <<
" removed)";
1925 <<
" exceeds the number of trusted validators ("
1935 return trustChanges;
1964 auto ret = std::move(validations);
1973 [&](
auto const& v) ->
bool {
1974 if (auto const masterKey =
1975 getTrustedKey(read_lock, v->getSignerPublic());
1978 return negativeUNL_.count(*masterKey);