1#include <xrpld/app/misc/HashRouter.h>
2#include <xrpld/app/misc/NetworkOPs.h>
3#include <xrpld/app/misc/ValidatorList.h>
4#include <xrpld/overlay/Overlay.h>
6#include <xrpl/basics/FileUtilities.h>
7#include <xrpl/basics/Slice.h>
8#include <xrpl/basics/StringUtilities.h>
9#include <xrpl/basics/base64.h>
10#include <xrpl/json/json_reader.h>
11#include <xrpl/protocol/PublicKey.h>
12#include <xrpl/protocol/STValidation.h>
13#include <xrpl/protocol/digest.h>
14#include <xrpl/protocol/jss.h>
15#include <xrpl/protocol/messages.h>
17#include <boost/regex.hpp>
35 return "same_sequence";
39 return "known_sequence";
41 return "unsupported_version";
62 : publisherKey(key), status(stat), sequence(seq)
71 : dispositions.begin()->first;
78 : dispositions.rbegin()->first;
87 dispositions[disp] +=
count;
95 : message(message_), hash(hash_), numVLs(num_)
113 ,
quorum_(minimumQuorum.value_or(1))
126 static boost::regex
const re(
141 <<
"Loading configured trusted validator list publisher keys";
144 for (
auto key : publisherKeys)
146 JLOG(
j_.
trace()) <<
"Processing '" << key <<
"'";
152 JLOG(
j_.
error()) <<
"Invalid validator list publisher key: " << key;
162 <<
"Configured validator list publisher key is revoked: "
170 <<
"Duplicate validator list publisher key: " << key;
184 "xrpl::ValidatorList::load : list threshold inside range");
185 JLOG(
j_.
debug()) <<
"Validator list threshold set in configuration to "
194 JLOG(
j_.
debug()) <<
"Validator list threshold computed as "
208 auto const [_, inserted] =
212 JLOG(
j_.
debug()) <<
"Added own master key "
217 JLOG(
j_.
debug()) <<
"Loading configured validator keys";
220 for (
auto const& n : configKeys)
222 JLOG(
j_.
trace()) <<
"Processing '" << n <<
"'";
226 if (!boost::regex_match(n,
match, re))
228 JLOG(
j_.
error()) <<
"Malformed entry: '" << n <<
"'";
237 JLOG(
j_.
error()) <<
"Invalid node identity: " <<
match[1];
248 JLOG(
j_.
warn()) <<
"Duplicate node identity: " <<
match[1];
266boost::filesystem::path
296 "xrpl::ValidatorList::buildFileData : valid publisher list input");
297 auto const effectiveVersion =
298 forceVersion ? *forceVersion : pubCollection.
rawVersion;
301 value[jss::version] = effectiveVersion;
302 value[jss::public_key] = pubKey;
304 switch (effectiveVersion)
308 value[jss::blob] =
current.rawBlob;
309 value[jss::signature] =
current.rawSignature;
314 value[jss::manifest] = *
current.rawManifest;
320 auto add = [&blobs, &outerManifest = pubCollection.
rawManifest](
323 blob[jss::blob] = pubList.rawBlob;
324 blob[jss::signature] = pubList.rawSignature;
325 if (pubList.rawManifest &&
326 *pubList.rawManifest != outerManifest)
327 blob[jss::manifest] = *pubList.rawManifest;
337 value[jss::blobs_v2] = std::move(blobs);
342 <<
"Invalid VL version provided: " << effectiveVersion;
359 boost::system::error_code ec;
367 value[jss::refresh_interval] = 24 * 60;
374 JLOG(
j_.
error()) <<
"Problem writing " << filename <<
" " << ec.value()
375 <<
": " << ec.message();
398 "xrpl::ValidatorList::parseBlobs : single element result");
407 if (!body.
isMember(jss::blobs_v2) ||
408 !body[jss::blobs_v2].
isArray() ||
413 auto const& blobs = body[jss::blobs_v2];
415 for (
auto const& blobInfo : blobs)
417 if (!blobInfo.isObject() ||
418 !blobInfo.isMember(jss::signature) ||
419 !blobInfo[jss::signature].isString() ||
420 !blobInfo.isMember(jss::blob) ||
421 !blobInfo[jss::blob].isString())
424 info.
blob = blobInfo[jss::blob].asString();
425 info.
signature = blobInfo[jss::signature].asString();
426 if (blobInfo.isMember(jss::manifest))
428 if (!blobInfo[jss::manifest].isString())
430 info.
manifest = blobInfo[jss::manifest].asString();
434 result.
size() == blobs.size(),
435 "xrpl::ValidatorList::parseBlobs(version, Jason::Value) : "
436 "result size matches");
446 return {{body.blob(), body.signature(), {}}};
456 result.
reserve(body.blobs_size());
457 for (
auto const& blob : body.blobs())
460 info.
blob = blob.blob();
462 if (blob.has_manifest())
468 result.
size() == body.blobs_size(),
469 "xrpl::ValidatorList::parseBlobs(TMValidatorList) : result size "
477 protocol::TMValidatorListCollection
const& largeMsg,
485 protocol::TMValidatorListCollection
const& largeMsg,
490 if (begin == 0 && end == 0)
491 end = largeMsg.blobs_size();
492 XRPL_ASSERT(begin < end,
"xrpl::splitMessage : valid inputs");
496 auto mid = (begin + end) / 2;
506 protocol::TMValidatorListCollection
const& largeMsg,
513 if (end - begin == 1)
515 protocol::TMValidatorList smallMsg;
516 smallMsg.set_version(1);
517 smallMsg.set_manifest(largeMsg.manifest());
519 auto const& blob = largeMsg.blobs(begin);
520 smallMsg.set_blob(blob.blob());
521 smallMsg.set_signature(blob.signature());
523 if (blob.has_manifest())
524 smallMsg.set_manifest(blob.manifest());
528 "xrpl::splitMessageParts : maximum message size");
534 return messages.
back().numVLs;
540 smallMsg->set_version(largeMsg.version());
541 smallMsg->set_manifest(largeMsg.manifest());
545 *smallMsg->add_blobs() = largeMsg.blobs(i);
552 return splitMessage(messages, largeMsg, maxSize, begin, end);
558 *smallMsg, protocol::mtVALIDATORLISTCOLLECTION),
560 smallMsg->blobs_size());
561 return messages.
back().numVLs;
578 "xrpl::buildValidatorListMessage(ValidatorBlobInfo) : empty messages "
580 protocol::TMValidatorList msg;
583 auto const version = 1;
585 msg.set_blob(currentBlob.
blob);
586 msg.set_signature(currentBlob.
signature);
588 msg.set_version(version);
592 "xrpl::buildValidatorListMessage(ValidatorBlobInfo) : maximum "
614 "xrpl::buildValidatorListMessage(std::map<std::size_t, "
615 "ValidatorBlobInfo>) : empty messages input");
616 protocol::TMValidatorListCollection msg;
617 auto const version = rawVersion < 2 ? 2 : rawVersion;
618 msg.set_version(version);
619 msg.set_manifest(rawManifest);
621 for (
auto const& [sequence, blobInfo] : blobInfos)
623 if (sequence <= peerSequence)
625 protocol::ValidatorBlobInfo& blob = *msg.add_blobs();
626 blob.set_blob(blobInfo.blob);
627 blob.set_signature(blobInfo.signature);
628 if (blobInfo.manifest)
629 blob.set_manifest(*blobInfo.manifest);
632 msg.blobs_size() > 0,
633 "xrpl::buildValidatorListMessage(std::map<std::size_t, "
634 "ValidatorBlobInfo>) : minimum message blobs");
646 return messages.
back().numVLs;
665 "xrpl::ValidatorList::buildValidatorListMessages : empty messages "
667 auto const& [currentSeq, currentBlob] = *blobInfos.
begin();
673 return total + m.numVLs;
675 if (messageVersion == 2 && peerSequence < maxSequence)
678 if (messages.
empty())
687 if (messages.
empty())
694 return {maxSequence, numVLs};
696 else if (messageVersion == 1 && peerSequence < currentSeq)
699 if (messages.
empty())
704 currentBlob.manifest ? *currentBlob.manifest : rawManifest,
707 if (messages.
empty())
714 return {currentSeq, numVLs};
751 "xrpl::ValidatorList::sendValidatorList : non-empty messages "
757 for (
auto const& message : messages)
761 peer.
send(message.message);
769 sent || messages.
size() == 1,
770 "xrpl::ValidatorList::sendValidatorList : sent or one message");
773 if (messageVersion > 1)
775 <<
"Sent " << messages.
size()
776 <<
" validator list collection(s) containing " << numVLs
777 <<
" validator list(s) for " <<
strHex(publisherKey)
778 <<
" with sequence range " << peerSequence <<
", "
779 << newPeerSequence <<
" to " << peer.
fingerprint();
784 "xrpl::ValidatorList::sendValidatorList : one validator "
787 <<
"Sent validator list for " <<
strHex(publisherKey)
788 <<
" with sequence " << newPeerSequence <<
" to "
830 blobInfos[
current.sequence] = {
832 for (
auto const& [sequence, vl] : remaining)
834 blobInfos[sequence] = {vl.rawBlob, vl.rawSignature, vl.rawManifest};
882 "xrpl::ValidatorList::broadcastBlobs : valid sequence");
887 if (toSkip->count(peer->id()) == 0)
889 auto const peerSequence =
890 peer->publisherListSequence(publisherKey).value_or(0);
891 if (peerSequence < maxSequence)
893 if (blobInfos.
empty())
895 auto const v2 = peer->supportsFeature(
905 v2 ? messages2[peerSequence] : messages1,
910 hashRouter.addSuppressionPeer(hash, peer->id());
930 auto const disposition = result.bestDisposition();
957 result.publisherKey &&
963 *result.publisherKey,
965 *pubCollection.maxSequence,
992 for (
auto const& blobInfo : blobs)
1008 stats.mergeDispositions(result);
1009 result = std::move(stats);
1021 auto& remaining = pubCollection.remaining;
1022 auto const&
current = pubCollection.current;
1023 for (
auto iter = remaining.begin(); iter != remaining.end();)
1027 next == remaining.end() || next->first > iter->first,
1028 "xrpl::ValidatorList::applyLists : next is valid");
1029 if (iter->first <=
current.sequence ||
1030 (next != remaining.end() &&
1031 next->second.validFrom <= iter->second.validFrom))
1033 iter = remaining.erase(iter);
1043 pubCollection.fullHash =
sha512Half(pubCollection);
1045 result.
sequence = *pubCollection.maxSequence;
1061 auto iNew = publisherList.
begin();
1062 auto iOld = oldList.
begin();
1063 while (iNew != publisherList.
end() || iOld != oldList.
end())
1065 if (iOld == oldList.
end() ||
1066 (iNew != publisherList.
end() && *iNew < *iOld))
1073 iNew == publisherList.
end() ||
1074 (iOld != oldList.
end() && *iOld < *iNew))
1090 if (publisherList.
empty())
1092 JLOG(
j_.
warn()) <<
"No validator keys included in valid list";
1095 for (
auto const& valManifest : manifests)
1102 <<
" contained untrusted validator manifest";
1110 <<
" contained invalid validator manifest";
1126 using namespace std::string_literals;
1129 auto const&
manifest = localManifest ? *localManifest : globalManifest;
1133 JLOG(
j_.
warn()) <<
"UNL manifest cannot be deserialized";
1137 auto [result, pubKeyOpt] =
1138 verify(lock, list, std::move(*m), blob, signature);
1143 <<
"UNL manifest is signed with an unrecognized master public key";
1154 UNREACHABLE(
"xrpl::ValidatorList::applyList : invalid public key type");
1165 if (pubCollection.maxSequence &&
1174 pubCollection.status,
1175 *pubCollection.maxSequence};
1183 auto const sequence = list[jss::sequence].
asUInt();
1192 pubCollection.rawManifest = globalManifest;
1193 if (!pubCollection.maxSequence || sequence > *pubCollection.maxSequence)
1194 pubCollection.maxSequence = sequence;
1196 Json::Value const& newList = list[jss::validators];
1198 if (
accepted && pubCollection.remaining.count(sequence) != 0)
1205 auto& publisher = pubCollection.current;
1207 oldList = std::move(pubCollection.current.list);
1209 publisher = std::move(pubCollection.remaining[sequence]);
1211 pubCollection.remaining.erase(sequence);
1214 publisher.sequence == sequence,
1215 "xrpl::ValidatorList::applyList : publisher sequence match");
1219 auto& publisher =
accepted ? pubCollection.current
1220 : pubCollection.remaining[sequence];
1221 publisher.sequence = sequence;
1223 list.
isMember(jss::effective) ? list[jss::effective].
asUInt() : 0}};
1226 publisher.siteUri = std::move(siteUri);
1227 publisher.rawBlob = blob;
1228 publisher.rawSignature = signature;
1229 publisher.rawManifest = localManifest;
1231 publisher.hash = *hash;
1237 oldList = std::move(publisherList);
1239 publisherList.
clear();
1241 for (
auto const& val : newList)
1243 if (val.isObject() && val.isMember(jss::validation_public_key) &&
1244 val[jss::validation_public_key].isString())
1247 strUnHex(val[jss::validation_public_key].asString());
1252 <<
"Invalid node identity: "
1253 << val[jss::validation_public_key].asString();
1261 if (val.isMember(jss::manifest) &&
1262 val[jss::manifest].isString())
1263 manifests.
push_back(val[jss::manifest].asString());
1272 pubCollection.rawVersion =
std::max(pubCollection.rawVersion, version);
1273 if (!pubCollection.remaining.empty())
1277 pubCollection.rawVersion =
std::max(pubCollection.rawVersion, 2u);
1281 result, pubKey, pubCollection.status, *pubCollection.maxSequence};
1294 using namespace std::string_literals;
1295 using namespace boost::filesystem;
1296 using namespace boost::system::errc;
1304 boost::system::error_code ec;
1311 auto const fullPath{
canonical(filename, ec)};
1315 auto size = file_size(fullPath, ec);
1328 return fullPath.root_path() ==
"/"s ?
"file://" :
"file:///";
1374 auto const sig =
strUnHex(signature);
1380 if (!r.
parse(data, list))
1383 if (list.
isMember(jss::sequence) && list[jss::sequence].
isInt() &&
1384 list.
isMember(jss::expiration) && list[jss::expiration].
isInt() &&
1385 (!list.
isMember(jss::effective) || list[jss::effective].
isInt()) &&
1388 auto const sequence = list[jss::sequence].
asUInt();
1390 list.
isMember(jss::effective) ? list[jss::effective].
asUInt() : 0}};
1395 if (validUntil <= validFrom)
1397 else if (sequence < listCollection.current.sequence)
1399 else if (sequence == listCollection.current.sequence)
1401 else if (validUntil <= now)
1403 else if (validFrom > now)
1414 return !listCollection.maxSequence ||
1415 sequence > *listCollection.maxSequence ||
1416 (listCollection.remaining.count(sequence) == 0 &&
1417 validFrom < listCollection.remaining
1418 .at(*listCollection.maxSequence)
1453 return trusted(read_lock, identity);
1510 "xrpl::ValidatorList::removePublisherList : valid reason input");
1515 JLOG(
j_.
debug()) <<
"Removing validator list for publisher "
1518 for (
auto const& val : iList->second.current.list)
1524 if (iVal->second <= 1)
1530 iList->second.current.list.clear();
1531 iList->second.status = reason;
1546 return count(read_lock);
1556 auto const&
current = collection.current;
1565 auto chainedExpiration =
current.validUntil;
1566 for (
auto const& [sequence, check] : collection.remaining)
1569 if (check.validFrom <= chainedExpiration)
1570 chainedExpiration = check.validUntil;
1576 if (!res || chainedExpiration < *res)
1578 res = chainedExpiration;
1582 if (localPublisherList.list.size() > 0)
1584 PublisherList collection = localPublisherList;
1586 auto const&
current = collection;
1587 auto chainedExpiration =
current.validUntil;
1590 if (!res || chainedExpiration < *res)
1592 res = chainedExpiration;
1599ValidatorList::expires()
const
1602 return expires(read_lock);
1606ValidatorList::getJson()
const
1612 res[jss::validation_quorum] =
static_cast<Json::UInt>(quorum_);
1617 x[jss::count] =
static_cast<Json::UInt>(count(read_lock));
1619 if (
auto when = expires(read_lock))
1621 if (*when == TimeKeeper::time_point::max())
1623 x[jss::expiration] =
"never";
1624 x[jss::status] =
"active";
1628 x[jss::expiration] = to_string(*when);
1630 if (*when > timeKeeper_.now())
1631 x[jss::status] =
"active";
1633 x[jss::status] =
"expired";
1638 x[jss::status] =
"unknown";
1639 x[jss::expiration] =
"unknown";
1642 x[jss::validator_list_threshold] =
Json::UInt(listThreshold_);
1649 for (
auto const& key : localPublisherList.list)
1655 for (
auto const& [publicKey, pubCollection] : publisherLists_)
1658 curr[jss::pubkey_publisher] =
strHex(publicKey);
1659 curr[jss::available] =
1660 pubCollection.status == PublisherStatus::available;
1664 target[jss::uri] = publisherList.
siteUri;
1669 target[jss::expiration] = to_string(publisherList.
validUntil);
1672 target[jss::effective] = to_string(publisherList.
validFrom);
1674 for (
auto const& key : publisherList.
list)
1680 auto const&
current = pubCollection.current;
1684 curr[jss::version] = pubCollection.rawVersion;
1689 for (
auto const& [sequence, future] : pubCollection.remaining)
1691 using namespace std::chrono_literals;
1695 appendList(future, r);
1698 future.validFrom > timeKeeper_.now() + 600s,
1699 "xrpl::ValidatorList::getJson : minimum valid from");
1701 if (remaining.
size())
1702 curr[jss::remaining] = std::move(remaining);
1708 for (
auto const& k : trustedMasterKeys_)
1715 validatorManifests_.for_each_manifest([&jSigningKeys,
1716 this](Manifest
const& manifest) {
1717 auto it = keyListings_.find(manifest.masterKey);
1718 if (it != keyListings_.end() && manifest.signingKey)
1720 jSigningKeys[toBase58(TokenType::NodePublic, manifest.masterKey)] =
1721 toBase58(TokenType::NodePublic, *manifest.signingKey);
1726 if (!negativeUNL_.empty())
1729 for (
auto const& k : negativeUNL_)
1739ValidatorList::for_each_listed(
1744 for (
auto const& v : keyListings_)
1745 func(v.first, trusted(read_lock, v.first));
1749ValidatorList::for_each_available(
1756 uint256 const& hash)> func)
const
1760 for (
auto const& [key, plCollection] : publisherLists_)
1762 if (plCollection.status != PublisherStatus::available)
1765 plCollection.maxSequence != 0,
1766 "xrpl::ValidatorList::for_each_available : nonzero maxSequence");
1768 plCollection.rawManifest,
1769 plCollection.rawVersion,
1770 buildBlobInfos(plCollection),
1772 plCollection.maxSequence.value_or(0),
1773 plCollection.fullHash);
1778ValidatorList::getAvailable(
1788 JLOG(j_.warn()) <<
"Invalid requested validator list publisher key: "
1795 auto const iter = publisherLists_.find(
id);
1797 if (iter == publisherLists_.end() ||
1798 iter->second.status != PublisherStatus::available)
1802 buildFileData(
std::string{pubKey}, iter->second, forceVersion, j_);
1808ValidatorList::calculateQuorum(
1814 if (minimumQuorum_ > 0)
1816 JLOG(j_.warn()) <<
"Using potentially unsafe quorum of "
1818 <<
" as specified on the command line";
1819 return *minimumQuorum_;
1822 if (!publisherLists_.empty())
1827 for (
auto const& list : publisherLists_)
1829 if (list.second.status != PublisherStatus::available)
1851 auto const errorThreshold =
std::min(
1853 publisherLists_.size() - listThreshold_ + 1);
1856 "xrpl::ValidatorList::calculateQuorum : nonzero error threshold");
1900ValidatorList::updateTrusted(
1907 using namespace std::chrono_literals;
1908 if (timeKeeper_.now() > closeTime + 30s)
1909 closeTime = timeKeeper_.now();
1918 for (
auto& [pubKey, collection] : publisherLists_)
1921 auto& remaining = collection.remaining;
1922 auto const firstIter = remaining.begin();
1923 auto iter = firstIter;
1924 if (iter != remaining.end() && iter->second.validFrom <= closeTime)
1927 for (
auto next =
std::next(iter); next != remaining.end() &&
1928 next->second.validFrom <= closeTime;
1933 "xrpl::ValidatorList::updateTrusted : sequential "
1937 iter != remaining.end(),
1938 "xrpl::ValidatorList::updateTrusted : non-end of "
1942 auto sequence = iter->first;
1943 auto& candidate = iter->second;
1944 auto&
current = collection.current;
1946 candidate.validFrom <= closeTime,
1947 "xrpl::ValidatorList::updateTrusted : maximum time");
1949 auto const oldList =
current.list;
1950 current = std::move(candidate);
1951 if (collection.status != PublisherStatus::available)
1952 collection.status = PublisherStatus::available;
1955 "xrpl::ValidatorList::updateTrusted : sequence match");
1959 if (
current.validUntil <= closeTime)
1962 updatePublisherList(pubKey,
current, oldList, lock);
1979 remaining.erase(firstIter,
std::next(iter));
1985 if (collection.status == PublisherStatus::available &&
1986 collection.current.validUntil <= closeTime)
1988 removePublisherList(lock, pubKey, PublisherStatus::expired);
1991 if (collection.status != PublisherStatus::available)
1999 auto it = trustedMasterKeys_.cbegin();
2000 while (it != trustedMasterKeys_.cend())
2002 auto const kit = keyListings_.find(*it);
2003 if (kit == keyListings_.end() ||
2004 kit->second < listThreshold_ ||
2005 validatorManifests_.revoked(*it))
2008 it = trustedMasterKeys_.erase(it);
2013 kit->second >= listThreshold_,
2014 "xrpl::ValidatorList::updateTrusted : count meets threshold");
2019 for (
auto const& val : keyListings_)
2021 if (val.second >= listThreshold_ &&
2022 !validatorManifests_.revoked(val.first) &&
2023 trustedMasterKeys_.emplace(val.first).second)
2029 if (!trustChanges.
added.empty() || !trustChanges.
removed.empty())
2031 trustedSigningKeys_.clear();
2035 for (
auto const& k : trustedMasterKeys_)
2038 validatorManifests_.getSigningKey(k);
2041 "xrpl::ValidatorList::updateTrusted : found signing key");
2042 trustedSigningKeys_.insert(*signingKey);
2047 << trustedMasterKeys_.size() <<
" of " << keyListings_.size()
2048 <<
" listed validators eligible for inclusion in the trusted set";
2050 auto const unlSize = trustedMasterKeys_.size();
2051 auto effectiveUnlSize = unlSize;
2052 auto seenSize = seenValidators.
size();
2053 if (!negativeUNL_.empty())
2055 for (
auto const& k : trustedMasterKeys_)
2057 if (negativeUNL_.count(k))
2061 for (
auto const& k : negativeUNL_)
2065 for (
auto const& nid : seenValidators)
2067 if (negUnlNodeIDs.
count(nid))
2071 quorum_ = calculateQuorum(unlSize, effectiveUnlSize, seenSize);
2073 JLOG(j_.debug()) <<
"Using quorum of " << quorum_ <<
" for new set of "
2074 << unlSize <<
" trusted validators ("
2075 << trustChanges.
added.size() <<
" added, "
2076 << trustChanges.
removed.size() <<
" removed)";
2078 if (unlSize < quorum_)
2080 JLOG(j_.warn()) <<
"New quorum of " << quorum_
2081 <<
" exceeds the number of trusted validators ("
2085 if ((publisherLists_.size() || localPublisherList.list.size()) &&
2092 return trustChanges;
2096ValidatorList::getTrustedMasterKeys()
const
2099 return trustedMasterKeys_;
2103ValidatorList::getListThreshold()
const
2106 return listThreshold_;
2110ValidatorList::getNegativeUNL()
const
2113 return negativeUNL_;
2120 negativeUNL_ = negUnl;
2124ValidatorList::negativeUNLFilter(
2128 auto ret = std::move(validations);
2131 if (!negativeUNL_.empty())
2137 [&](
auto const& v) ->
bool {
2138 if (auto const masterKey =
2139 getTrustedKey(read_lock, v->getSignerPublic());
2142 return negativeUNL_.count(*masterKey);
Unserialize a JSON document into a Value.
bool parse(std::string const &document, Value &root)
Read a Value from a JSON document.
Value & append(Value const &value)
Append value to array at the end.
UInt size() const
Number of values in array or object.
std::string toStyledString() const
std::string asString() const
Returns the unquoted string value.
bool isMember(char const *key) const
Return true if the object has a member named key.
A generic endpoint for log messages.
Stream trace() const
Severity stream access functions.
typename Clock::time_point time_point
typename Clock::duration duration
Routing table for objects identified by hash.
std::optional< std::set< PeerShortID > > shouldRelay(uint256 const &key)
Determines whether the hashed item should be relayed.
bool addSuppressionPeer(uint256 const &key, PeerShortID peer)
Remembers manifests with the highest sequence number.
std::optional< PublicKey > getSigningKey(PublicKey const &pk) const
Returns master key's current signing key.
ManifestDisposition applyManifest(Manifest m)
Add manifest to cache.
PublicKey getMasterKey(PublicKey const &pk) const
Returns ephemeral signing key's master public key.
bool revoked(PublicKey const &pk) const
Returns true if master key has been revoked in a manifest.
static std::size_t totalSize(::google::protobuf::Message const &message)
Provides server functionality for clients.
virtual void clearUNLBlocked()=0
virtual void setUNLBlocked()=0
Manages the set of connected peers.
virtual PeerSequence getActivePeers() const =0
Returns a sequence representing the current list of peers.
Represents a peer connection in the overlay.
virtual std::string const & fingerprint() const =0
virtual void setPublisherListSequence(PublicKey const &, std::size_t const)=0
virtual void send(std::shared_ptr< Message > const &m)=0
virtual id_t id() const =0
virtual bool supportsFeature(ProtocolFeature f) const =0
std::size_t size() const noexcept
const_iterator end() const noexcept
An immutable linear range of bytes.
Manages various times used by the server.
time_point now() const override
Returns the current time, using the server's clock.
static void sendValidatorList(Peer &peer, std::uint64_t peerSequence, PublicKey const &publisherKey, std::size_t maxSequence, std::uint32_t rawVersion, std::string const &rawManifest, std::map< std::size_t, ValidatorBlobInfo > const &blobInfos, HashRouter &hashRouter, beast::Journal j)
static constexpr std::uint32_t supportedListVersions[]
PublisherList localPublisherList
hash_set< PublicKey > trustedMasterKeys_
bool trustedPublisher(PublicKey const &identity) const
Returns true if public key is a trusted publisher.
static constexpr std::size_t maxSupportedBlobs
ValidatorList(ManifestCache &validatorManifests, ManifestCache &publisherManifests, TimeKeeper &timeKeeper, std::string const &databasePath, beast::Journal j, std::optional< std::size_t > minimumQuorum=std::nullopt)
static Json::Value buildFileData(std::string const &pubKey, PublisherListCollection const &pubCollection, beast::Journal j)
Build a Json representation of the collection, suitable for writing to a cache file,...
std::vector< std::string > loadLists()
std::optional< PublicKey > localPubKey_
std::atomic< std::size_t > quorum_
std::pair< ListDisposition, std::optional< PublicKey > > verify(lock_guard const &, Json::Value &list, Manifest manifest, std::string const &blob, std::string const &signature)
Check response for trusted valid published list.
boost::filesystem::path const dataPath_
bool load(std::optional< PublicKey > const &localSigningKey, std::vector< std::string > const &configKeys, std::vector< std::string > const &publisherKeys, std::optional< std::size_t > listThreshold={})
Load configured trusted keys.
bool removePublisherList(lock_guard const &, PublicKey const &publisherKey, PublisherStatus reason)
Stop trusting publisher's list of keys.
PublisherListStats applyLists(std::string const &manifest, std::uint32_t version, std::vector< ValidatorBlobInfo > const &blobs, std::string siteUri, std::optional< uint256 > const &hash={})
Apply multiple published lists of public keys.
std::optional< PublicKey > localPublicKey() const
This function returns the local validator public key or a std::nullopt.
static std::pair< std::size_t, std::size_t > buildValidatorListMessages(std::size_t messageVersion, std::uint64_t peerSequence, std::size_t maxSequence, std::uint32_t rawVersion, std::string const &rawManifest, std::map< std::size_t, ValidatorBlobInfo > const &blobInfos, std::vector< MessageWithHash > &messages, std::size_t maxSize=maximiumMessageSize)
PublisherListStats applyList(std::string const &globalManifest, std::optional< std::string > const &localManifest, std::string const &blob, std::string const &signature, std::uint32_t version, std::string siteUri, std::optional< uint256 > const &hash, lock_guard const &)
Apply published list of public keys.
std::optional< PublicKey > getListedKey(PublicKey const &identity) const
Returns listed master public if public key is included on any lists.
void cacheValidatorFile(lock_guard const &lock, PublicKey const &pubKey) const
Write a JSON UNL to a cache file.
std::optional< std::size_t > minimumQuorum_
static std::vector< ValidatorBlobInfo > parseBlobs(std::uint32_t version, Json::Value const &body)
Pull the blob/signature/manifest information out of the appropriate Json body fields depending on the...
ManifestCache & publisherManifests_
hash_map< PublicKey, std::size_t > keyListings_
std::optional< TimeKeeper::time_point > expires() const
Return the time when the validator list will expire.
static void buildBlobInfos(std::map< std::size_t, ValidatorBlobInfo > &blobInfos, PublisherListCollection const &lists)
ManifestCache & validatorManifests_
std::size_t listThreshold_
static void broadcastBlobs(PublicKey const &publisherKey, PublisherListCollection const &lists, std::size_t maxSequence, uint256 const &hash, Overlay &overlay, HashRouter &hashRouter, beast::Journal j)
std::size_t count() const
Return the number of configured validator list sites.
std::optional< PublicKey > getTrustedKey(PublicKey const &identity) const
Returns master public key if public key is trusted.
void updatePublisherList(PublicKey const &pubKey, PublisherList const ¤t, std::vector< PublicKey > const &oldList, lock_guard const &)
PublisherListStats applyListsAndBroadcast(std::string const &manifest, std::uint32_t version, std::vector< ValidatorBlobInfo > const &blobs, std::string siteUri, uint256 const &hash, Overlay &overlay, HashRouter &hashRouter, NetworkOPs &networkOPs)
Apply multiple published lists of public keys, then broadcast it to all peers that have not seen it o...
boost::filesystem::path getCacheFileName(lock_guard const &, PublicKey const &pubKey) const
Get the filename used for caching UNLs.
bool trusted(PublicKey const &identity) const
Returns true if public key is trusted.
static std::string const filePrefix_
bool listed(PublicKey const &identity) const
Returns true if public key is included on any lists.
hash_map< PublicKey, PublisherListCollection > publisherLists_
T emplace_back(T... args)
@ arrayValue
array value (ordered list)
@ objectValue
object value (collection of name/value pairs).
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
std::error_code make_error_code(xrpl::TokenCodecErrc e)
sha512_half_hasher::result_type sha512Half(Args const &... args)
Returns the SHA512-Half of a series of objects.
std::string to_string(base_uint< Bits, Tag > const &a)
std::string strHex(FwdIt begin, FwdIt end)
std::string base64_decode(std::string_view data)
@ unsupported_version
List version is not supported.
@ stale
Trusted publisher key, but seq is too old.
@ untrusted
List signed by untrusted publisher key.
@ same_sequence
Same sequence as current list.
@ pending
List will be valid in the future.
@ known_sequence
Future sequence already seen.
@ expired
List is expired, but has the largest non-pending sequence seen so far.
@ invalid
Invalid format or signature.
bool verify(PublicKey const &publicKey, Slice const &m, Slice const &sig) noexcept
Verify a signature on a message.
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
@ ValidatorListPropagation
@ ValidatorList2Propagation
std::size_t splitMessage(std::vector< ValidatorList::MessageWithHash > &messages, protocol::TMValidatorListCollection const &largeMsg, std::size_t maxSize, std::size_t begin=0, std::size_t end=0)
std::size_t splitMessageParts(std::vector< ValidatorList::MessageWithHash > &messages, protocol::TMValidatorListCollection const &largeMsg, std::size_t maxSize, std::size_t begin, std::size_t end)
@ current
This was a new validation and was added.
std::optional< KeyType > publicKeyType(Slice const &slice)
Returns the type of public key.
std::optional< Manifest > deserializeManifest(Slice s, beast::Journal journal)
Constructs Manifest from serialized string.
std::size_t buildValidatorListMessage(std::vector< ValidatorList::MessageWithHash > &messages, std::uint32_t rawVersion, std::string const &rawManifest, ValidatorBlobInfo const ¤tBlob, std::size_t maxSize)
std::optional< Blob > strUnHex(std::size_t strSize, Iterator begin, Iterator end)
NodeID calcNodeID(PublicKey const &)
Calculate the 160-bit node ID from a node public key.
void writeFileContents(boost::system::error_code &ec, boost::filesystem::path const &destPath, std::string const &contents)
std::optional< Blob > strViewUnHex(std::string_view strSrc)
constexpr std::size_t maximiumMessageSize
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)
@ accepted
Manifest is valid.
@ invalid
Timely, but invalid signature.
Changes in trusted nodes after updating validator list.
hash_set< NodeID > removed
Used to represent the information stored in the blobs_v2 Json array.
std::optional< std::string > manifest
MessageWithHash()=default
std::map< std::size_t, PublisherList > remaining
Describes the result of processing a Validator List (UNL), including some of the information from the...
void mergeDispositions(PublisherListStats const &src)
PublisherListStats()=default
std::optional< PublicKey > publisherKey
ListDisposition worstDisposition() const
std::map< ListDisposition, std::size_t > dispositions
ListDisposition bestDisposition() const
std::vector< PublicKey > list
TimeKeeper::time_point validFrom
TimeKeeper::time_point validUntil