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/consensus/ConsensusParms.h>
28 #include <ripple/json/json_reader.h>
29 #include <ripple/overlay/Overlay.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;
202 JLOG(
j_.
debug()) <<
"Loading configured validator keys";
205 for (
auto const& n : configKeys)
207 JLOG(
j_.
trace()) <<
"Processing '" << n <<
"'";
211 if (!boost::regex_match(n, match, re))
213 JLOG(
j_.
error()) <<
"Malformed entry: '" << n <<
"'";
221 JLOG(
j_.
error()) <<
"Invalid node identity: " << match[1];
232 JLOG(
j_.
warn()) <<
"Duplicate node identity: " << match[1];
237 auto&
current = it->second.current;
239 current.validUntil = TimeKeeper::time_point::max();
240 current.list.emplace_back(*
id);
250 boost::filesystem::path
279 auto const effectiveVersion =
280 forceVersion ? *forceVersion : pubCollection.
rawVersion;
283 value[jss::version] = effectiveVersion;
284 value[jss::public_key] = pubKey;
286 switch (effectiveVersion)
290 value[jss::blob] =
current.rawBlob;
291 value[jss::signature] =
current.rawSignature;
296 value[jss::manifest] = *
current.rawManifest;
302 auto add = [&blobs, &outerManifest = pubCollection.
rawManifest](
305 blob[jss::blob] = pubList.rawBlob;
306 blob[jss::signature] = pubList.rawSignature;
307 if (pubList.rawManifest &&
308 *pubList.rawManifest != outerManifest)
309 blob[jss::manifest] = *pubList.rawManifest;
319 value[jss::blobs_v2] = std::move(blobs);
324 <<
"Invalid VL version provided: " << effectiveVersion;
341 boost::system::error_code ec;
349 value[jss::refresh_interval] = 24 * 60;
356 JLOG(
j_.
error()) <<
"Problem writing " << filename <<
" " << ec.value()
357 <<
": " << ec.message();
378 assert(result.
size() == 1);
387 if (!body.
isMember(jss::blobs_v2) ||
388 !body[jss::blobs_v2].
isArray() ||
393 auto const& blobs = body[jss::blobs_v2];
395 for (
auto const& blobInfo : blobs)
397 if (!blobInfo.isObject() ||
398 !blobInfo.isMember(jss::signature) ||
399 !blobInfo[jss::signature].isString() ||
400 !blobInfo.isMember(jss::blob) ||
401 !blobInfo[jss::blob].isString())
404 info.
blob = blobInfo[jss::blob].asString();
405 info.
signature = blobInfo[jss::signature].asString();
406 if (blobInfo.isMember(jss::manifest))
408 if (!blobInfo[jss::manifest].isString())
410 info.
manifest = blobInfo[jss::manifest].asString();
413 assert(result.
size() == blobs.size());
423 return {{body.blob(), body.signature(), {}}};
433 result.
reserve(body.blobs_size());
434 for (
auto const& blob : body.blobs())
437 info.
blob = blob.blob();
439 if (blob.has_manifest())
444 assert(result.
size() == body.blobs_size());
451 protocol::TMValidatorListCollection
const& largeMsg,
459 protocol::TMValidatorListCollection
const& largeMsg,
464 if (begin == 0 && end == 0)
465 end = largeMsg.blobs_size();
470 auto mid = (begin + end) / 2;
480 protocol::TMValidatorListCollection
const& largeMsg,
487 if (end - begin == 1)
489 protocol::TMValidatorList smallMsg;
490 smallMsg.set_version(1);
491 smallMsg.set_manifest(largeMsg.manifest());
493 auto const& blob = largeMsg.blobs(begin);
494 smallMsg.set_blob(blob.blob());
495 smallMsg.set_signature(blob.signature());
497 if (blob.has_manifest())
498 smallMsg.set_manifest(blob.manifest());
503 std::make_shared<Message>(smallMsg, protocol::mtVALIDATORLIST),
512 smallMsg->set_version(largeMsg.version());
513 smallMsg->set_manifest(largeMsg.manifest());
517 *smallMsg->add_blobs() = largeMsg.blobs(i);
524 return splitMessage(messages, largeMsg, maxSize, begin, end);
529 std::make_shared<Message>(
530 *smallMsg, protocol::mtVALIDATORLISTCOLLECTION),
532 smallMsg->blobs_size());
548 assert(messages.
empty());
549 protocol::TMValidatorList msg;
552 auto const version = 1;
554 msg.set_blob(currentBlob.
blob);
555 msg.set_signature(currentBlob.
signature);
557 msg.set_version(version);
561 std::make_shared<Message>(msg, protocol::mtVALIDATORLIST),
578 assert(messages.
empty());
579 protocol::TMValidatorListCollection msg;
580 auto const version = rawVersion < 2 ? 2 : rawVersion;
581 msg.set_version(version);
582 msg.set_manifest(rawManifest);
584 for (
auto const& [sequence, blobInfo] : blobInfos)
586 if (sequence <= peerSequence)
588 protocol::ValidatorBlobInfo& blob = *msg.add_blobs();
589 blob.set_blob(blobInfo.blob);
590 blob.set_signature(blobInfo.signature);
591 if (blobInfo.manifest)
592 blob.set_manifest(*blobInfo.manifest);
594 assert(msg.blobs_size() > 0);
603 std::make_shared<Message>(msg, protocol::mtVALIDATORLISTCOLLECTION),
623 assert(!blobInfos.
empty());
624 auto const& [currentSeq, currentBlob] = *blobInfos.
begin();
630 return total + m.numVLs;
632 if (messageVersion == 2 && peerSequence < maxSequence)
635 if (messages.
empty())
644 if (messages.
empty())
651 return {maxSequence, numVLs};
653 else if (messageVersion == 1 && peerSequence < currentSeq)
656 if (messages.
empty())
661 currentBlob.manifest ? *currentBlob.manifest : rawManifest,
664 if (messages.
empty())
671 return {currentSeq, numVLs};
707 assert(!messages.
empty());
712 for (
auto const& message : messages)
716 peer.
send(message.message);
723 assert(sent || messages.size() == 1);
726 if (messageVersion > 1)
728 <<
"Sent " << messages.size()
729 <<
" validator list collection(s) containing " << numVLs
730 <<
" validator list(s) for " <<
strHex(publisherKey)
731 <<
" with sequence range " << peerSequence <<
", "
732 << newPeerSequence <<
" to "
739 <<
"Sent validator list for " <<
strHex(publisherKey)
740 <<
" with sequence " << newPeerSequence <<
" to "
783 blobInfos[
current.sequence] = {
785 for (
auto const& [sequence, vl] : remaining)
787 blobInfos[sequence] = {vl.rawBlob, vl.rawSignature, vl.rawManifest};
834 lists.
remaining.count(maxSequence) == 1);
839 if (toSkip->count(peer->id()) == 0)
841 auto const peerSequence =
842 peer->publisherListSequence(publisherKey).value_or(0);
843 if (peerSequence < maxSequence)
845 if (blobInfos.
empty())
847 auto const v2 = peer->supportsFeature(
857 v2 ? messages2[peerSequence] : messages1,
882 auto const disposition = result.bestDisposition();
908 pubCollection.maxSequence);
910 *result.publisherKey,
912 *pubCollection.maxSequence,
939 for (
auto const& blobInfo : blobs)
955 stats.mergeDispositions(result);
956 result = std::move(stats);
968 auto& remaining = pubCollection.remaining;
969 auto const&
current = pubCollection.current;
970 for (
auto iter = remaining.begin(); iter != remaining.end();)
973 assert(next == remaining.end() || next->first > iter->first);
974 if (iter->first <=
current.sequence ||
975 (next != remaining.end() &&
976 next->second.validFrom <= iter->second.validFrom))
978 iter = remaining.erase(iter);
988 pubCollection.fullHash =
sha512Half(pubCollection);
990 result.
sequence = *pubCollection.maxSequence;
1006 auto iNew = publisherList.
begin();
1007 auto iOld = oldList.
begin();
1008 while (iNew != publisherList.
end() || iOld != oldList.
end())
1010 if (iOld == oldList.
end() ||
1011 (iNew != publisherList.
end() && *iNew < *iOld))
1018 iNew == publisherList.
end() ||
1019 (iOld != oldList.
end() && *iOld < *iNew))
1035 if (publisherList.
empty())
1037 JLOG(
j_.
warn()) <<
"No validator keys included in valid list";
1040 for (
auto const& valManifest : manifests)
1047 <<
" contained untrusted validator manifest";
1055 <<
" contained invalid validator manifest";
1071 using namespace std::string_literals;
1075 auto const&
manifest = localManifest ? *localManifest : globalManifest;
1076 auto const result =
verify(lock, list, pubKey,
manifest, blob, signature);
1082 if (pubCollection.maxSequence &&
1091 pubCollection.status,
1092 *pubCollection.maxSequence};
1100 auto const sequence = list[jss::sequence].
asUInt();
1109 pubCollection.rawManifest = globalManifest;
1110 if (!pubCollection.maxSequence || sequence > *pubCollection.maxSequence)
1111 pubCollection.maxSequence = sequence;
1113 Json::Value const& newList = list[jss::validators];
1115 if (
accepted && pubCollection.remaining.count(sequence) != 0)
1122 auto& publisher = pubCollection.current;
1124 oldList = std::move(pubCollection.current.list);
1126 publisher = std::move(pubCollection.remaining[sequence]);
1128 pubCollection.remaining.erase(sequence);
1130 assert(publisher.sequence == sequence);
1134 auto& publisher =
accepted ? pubCollection.current
1135 : pubCollection.remaining[sequence];
1136 publisher.sequence = sequence;
1138 list.
isMember(jss::effective) ? list[jss::effective].
asUInt() : 0}};
1141 publisher.siteUri = std::move(siteUri);
1142 publisher.rawBlob = blob;
1143 publisher.rawSignature = signature;
1144 publisher.rawManifest = localManifest;
1146 publisher.hash = *hash;
1152 oldList = std::move(publisherList);
1154 publisherList.
clear();
1156 for (
auto const& val : newList)
1158 if (val.isObject() && val.isMember(jss::validation_public_key) &&
1159 val[jss::validation_public_key].isString())
1162 strUnHex(val[jss::validation_public_key].asString());
1167 <<
"Invalid node identity: "
1168 << val[jss::validation_public_key].asString();
1176 if (val.isMember(jss::manifest) &&
1177 val[jss::manifest].isString())
1178 manifests.
push_back(val[jss::manifest].asString());
1187 pubCollection.rawVersion =
std::max(pubCollection.rawVersion, version);
1188 if (!pubCollection.remaining.empty())
1192 pubCollection.rawVersion =
std::max(pubCollection.rawVersion, 2u);
1196 result, pubKey, pubCollection.status, *pubCollection.maxSequence};
1209 using namespace std::string_literals;
1210 using namespace boost::filesystem;
1211 using namespace boost::system::errc;
1219 boost::system::error_code ec;
1226 auto const fullPath{canonical(filename, ec)};
1230 auto size = file_size(fullPath, ec);
1235 ec = make_error_code(no_such_file_or_directory);
1241 #if _MSC_VER // MSVC: Windows paths need a leading / added
1243 return fullPath.root_path() ==
"/"s ?
"file://" :
"file:///";
1273 pubKey = m->masterKey;
1274 auto const revoked = m->revoked();
1288 auto const sig =
strUnHex(signature);
1298 if (!r.
parse(data, list))
1301 if (list.
isMember(jss::sequence) && list[jss::sequence].
isInt() &&
1302 list.
isMember(jss::expiration) && list[jss::expiration].
isInt() &&
1303 (!list.
isMember(jss::effective) || list[jss::effective].
isInt()) &&
1306 auto const sequence = list[jss::sequence].
asUInt();
1308 list.
isMember(jss::effective) ? list[jss::effective].
asUInt() : 0}};
1313 if (validUntil <= validFrom)
1315 else if (sequence < listCollection.current.sequence)
1317 else if (sequence == listCollection.current.sequence)
1319 else if (validUntil <= now)
1321 else if (validFrom > now)
1332 return !listCollection.maxSequence ||
1333 sequence > *listCollection.maxSequence ||
1334 (listCollection.remaining.count(sequence) == 0 &&
1335 validFrom < listCollection.remaining
1336 .at(*listCollection.maxSequence)
1371 return trusted(read_lock, identity);
1382 return std::nullopt;
1393 return std::nullopt;
1432 JLOG(
j_.
debug()) <<
"Removing validator list for publisher "
1435 for (
auto const& val : iList->second.current.list)
1441 if (iVal->second <= 1)
1447 iList->second.current.list.clear();
1448 iList->second.status = reason;
1463 return count(read_lock);
1474 auto const&
current = collection.current;
1476 return std::nullopt;
1481 auto chainedExpiration =
current.validUntil;
1482 for (
auto const& [sequence, check] : collection.remaining)
1485 if (check.validFrom <= chainedExpiration)
1486 chainedExpiration = check.validUntil;
1492 if (!res || chainedExpiration < *res)
1494 res = chainedExpiration;
1521 if (
auto when =
expires(read_lock))
1523 if (*when == TimeKeeper::time_point::max())
1525 x[jss::expiration] =
"never";
1526 x[jss::status] =
"active";
1533 x[jss::status] =
"active";
1535 x[jss::status] =
"expired";
1540 x[jss::status] =
"unknown";
1541 x[jss::expiration] =
"unknown";
1551 for (
auto const& key : it->second.current.list)
1560 if (local == publicKey)
1563 curr[jss::pubkey_publisher] =
strHex(publicKey);
1564 curr[jss::available] =
1569 target[jss::uri] = publisherList.
siteUri;
1579 for (
auto const& key : publisherList.
list)
1585 auto const&
current = pubCollection.current;
1589 curr[jss::version] = pubCollection.rawVersion;
1594 for (
auto const& [sequence, future] : pubCollection.remaining)
1596 using namespace std::chrono_literals;
1600 appendList(future, r);
1604 if (remaining.
size())
1605 curr[jss::remaining] = std::move(remaining);
1619 this](Manifest
const& manifest) {
1648 func(v.first,
trusted(read_lock, v.first));
1659 uint256 const& hash)> func)
const
1667 assert(plCollection.maxSequence);
1669 plCollection.rawManifest,
1670 plCollection.rawVersion,
1673 plCollection.maxSequence.value_or(0),
1674 plCollection.fullHash);
1680 boost::beast::string_view
const& pubKey,
1689 JLOG(
j_.
info()) <<
"Invalid requested validator list publisher key: "
1717 JLOG(
j_.
warn()) <<
"Using potentially unsafe quorum of "
1719 <<
" as specified on the command line";
1779 using namespace std::chrono_literals;
1790 auto& remaining = collection.remaining;
1791 auto const firstIter = remaining.begin();
1792 auto iter = firstIter;
1793 if (iter != remaining.end() && iter->second.validFrom <= closeTime)
1796 for (
auto next =
std::next(iter); next != remaining.end() &&
1797 next->second.validFrom <= closeTime;
1802 assert(iter != remaining.end());
1805 auto sequence = iter->first;
1806 auto& candidate = iter->second;
1807 auto&
current = collection.current;
1808 assert(candidate.validFrom <= closeTime);
1810 auto const oldList =
current.list;
1811 current = std::move(candidate);
1814 assert(
current.sequence == sequence);
1818 if (
current.validUntil <= closeTime)
1838 remaining.erase(firstIter,
std::next(iter));
1843 collection.current.validUntil <= closeTime)
1879 if (!trustChanges.
added.empty() || !trustChanges.
removed.empty())
1889 <<
" listed validators eligible for inclusion in the trusted set";
1892 auto effectiveUnlSize = unlSize;
1893 auto seenSize = seenValidators.
size();
1906 for (
auto const& nid : seenValidators)
1908 if (negUnlNodeIDs.
count(nid))
1914 JLOG(
j_.
debug()) <<
"Using quorum of " <<
quorum_ <<
" for new set of "
1915 << unlSize <<
" trusted validators ("
1916 << trustChanges.
added.size() <<
" added, "
1917 << trustChanges.
removed.size() <<
" removed)";
1922 <<
" exceeds the number of trusted validators ("
1932 return trustChanges;
1961 auto ret = std::move(validations);
1970 [&](
auto const& v) ->
bool {
1971 if (auto const masterKey =
1972 getTrustedKey(read_lock, v->getSignerPublic());
1975 return negativeUNL_.count(*masterKey);