1#include <xrpld/app/misc/ValidatorList.h>
3#include <xrpld/core/TimeKeeper.h>
4#include <xrpld/overlay/Message.h>
5#include <xrpld/overlay/Overlay.h>
6#include <xrpld/overlay/Peer.h>
8#include <xrpl/basics/Blob.h>
9#include <xrpl/basics/FileUtilities.h>
10#include <xrpl/basics/Log.h>
11#include <xrpl/basics/Slice.h>
12#include <xrpl/basics/StringUtilities.h>
13#include <xrpl/basics/base64.h>
14#include <xrpl/basics/base_uint.h>
15#include <xrpl/basics/chrono.h>
16#include <xrpl/basics/strHex.h>
17#include <xrpl/beast/utility/Journal.h>
18#include <xrpl/beast/utility/instrumentation.h>
19#include <xrpl/core/HashRouter.h>
20#include <xrpl/json/json_forwards.h>
21#include <xrpl/json/json_reader.h>
22#include <xrpl/json/json_value.h>
23#include <xrpl/protocol/PublicKey.h>
24#include <xrpl/protocol/STValidation.h>
25#include <xrpl/protocol/UintTypes.h>
26#include <xrpl/protocol/digest.h>
27#include <xrpl/protocol/jss.h>
28#include <xrpl/protocol/tokens.h>
29#include <xrpl/server/Manifest.h>
30#include <xrpl/server/NetworkOPs.h>
32#include <boost/filesystem/operations.hpp>
33#include <boost/regex/v5/regex.hpp>
34#include <boost/regex/v5/regex_match.hpp>
35#include <boost/system/detail/errc.hpp>
36#include <boost/system/detail/error_code.hpp>
37#include <boost/system/errc.hpp>
72 return "same_sequence";
76 return "known_sequence";
78 return "unsupported_version";
147 ,
quorum_(minimumQuorum.value_or(1))
160 static boost::regex
const kRE(
174 JLOG(
j_.debug()) <<
"Loading configured trusted validator list publisher keys";
177 for (
auto const& key : publisherKeys)
179 JLOG(
j_.trace()) <<
"Processing '" << key <<
"'";
185 JLOG(
j_.error()) <<
"Invalid validator list publisher key: " << key;
194 JLOG(
j_.warn()) <<
"Configured validator list publisher key is revoked: " << key;
200 JLOG(
j_.warn()) <<
"Duplicate validator list publisher key: " << key;
214 "xrpl::ValidatorList::load : list threshold inside range");
215 JLOG(
j_.debug()) <<
"Validator list threshold set in configuration to " <<
listThreshold_;
222 JLOG(
j_.debug()) <<
"Validator list threshold computed as " <<
listThreshold_;
225 JLOG(
j_.debug()) <<
"Loaded " <<
count <<
" keys";
238 JLOG(
j_.debug()) <<
"Added own master key "
243 JLOG(
j_.debug()) <<
"Loading configured validator keys";
246 for (
auto const& n : configKeys)
248 JLOG(
j_.trace()) <<
"Processing '" << n <<
"'";
252 if (!boost::regex_match(n, match, kRE))
254 JLOG(
j_.error()) <<
"Malformed entry: '" << n <<
"'";
262 JLOG(
j_.error()) <<
"Invalid node identity: " << match[1];
273 JLOG(
j_.warn()) <<
"Duplicate node identity: " << match[1];
286 JLOG(
j_.debug()) <<
"Loaded " <<
count <<
" entries";
291boost::filesystem::path
319 "xrpl::ValidatorList::buildFileData : valid publisher list input");
320 auto const effectiveVersion = forceVersion ? *forceVersion : pubCollection.
rawVersion;
323 value[jss::version] = effectiveVersion;
324 value[jss::public_key] = pubKey;
326 switch (effectiveVersion)
329 auto const& current = pubCollection.
current;
330 value[jss::blob] = current.
rawBlob;
331 value[jss::signature] = current.rawSignature;
334 if (current.rawManifest && *current.rawManifest != pubCollection.
rawManifest)
335 value[jss::manifest] = *current.rawManifest;
344 blob[jss::blob] = pubList.rawBlob;
345 blob[jss::signature] = pubList.rawSignature;
346 if (pubList.rawManifest && *pubList.rawManifest != outerManifest)
347 blob[jss::manifest] = *pubList.rawManifest;
351 for (
auto const& [_, pending] : pubCollection.
remaining)
357 value[jss::blobs_v2] = std::move(blobs);
361 JLOG(j.
trace()) <<
"Invalid VL version provided: " << effectiveVersion;
377 boost::system::error_code ec;
384 value[jss::refresh_interval] = 24 * 60;
391 JLOG(
j_.error()) <<
"Problem writing " << filename <<
" " << ec.value() <<
": "
413 result.
size() == 1,
"xrpl::ValidatorList::parseBlobs : single element result");
427 auto const& blobs = body[jss::blobs_v2];
429 for (
auto const& blobInfo : blobs)
431 if (!blobInfo.isObject() || !blobInfo.isMember(jss::signature) ||
432 !blobInfo[jss::signature].isString() || !blobInfo.isMember(jss::blob) ||
433 !blobInfo[jss::blob].isString())
436 info.
blob = blobInfo[jss::blob].asString();
437 info.
signature = blobInfo[jss::signature].asString();
438 if (blobInfo.isMember(jss::manifest))
440 if (!blobInfo[jss::manifest].isString())
442 info.
manifest = blobInfo[jss::manifest].asString();
446 result.
size() == blobs.size(),
447 "xrpl::ValidatorList::parseBlobs(version, Jason::Value) : "
448 "result size matches");
458 return {{.blob = body.blob(), .signature = body.signature(), .manifest = {}}};
468 result.
reserve(body.blobs_size());
469 for (
auto const& blob : body.blobs())
472 info.
blob = blob.blob();
474 if (blob.has_manifest())
480 result.
size() == body.blobs_size(),
481 "xrpl::ValidatorList::parseBlobs(TMValidatorList) : result size "
489 protocol::TMValidatorListCollection
const& largeMsg,
497 protocol::TMValidatorListCollection
const& largeMsg,
502 if (begin == 0 && end == 0)
503 end = largeMsg.blobs_size();
504 XRPL_ASSERT(begin < end,
"xrpl::splitMessage : valid inputs");
508 auto mid = (begin + end) / 2;
518 protocol::TMValidatorListCollection
const& largeMsg,
525 if (end - begin == 1)
527 protocol::TMValidatorList smallMsg;
528 smallMsg.set_version(1);
529 smallMsg.set_manifest(largeMsg.manifest());
531 auto const& blob = largeMsg.blobs(begin);
532 smallMsg.set_blob(blob.blob());
533 smallMsg.set_signature(blob.signature());
535 if (blob.has_manifest())
536 smallMsg.set_manifest(blob.manifest());
540 "xrpl::splitMessageParts : maximum message size");
546 return messages.
back().numVLs;
551 smallMsg->set_version(largeMsg.version());
552 smallMsg->set_manifest(largeMsg.manifest());
556 *smallMsg->add_blobs() = largeMsg.blobs(i);
563 return splitMessage(messages, largeMsg, maxSize, begin, end);
569 smallMsg->blobs_size());
570 return messages.
back().numVLs;
584 "xrpl::buildValidatorListMessage(ValidatorBlobInfo) : empty messages "
586 protocol::TMValidatorList msg;
587 auto const manifest = currentBlob.
manifest ? *currentBlob.
manifest : rawManifest;
588 auto const version = 1;
589 msg.set_manifest(manifest);
590 msg.set_blob(currentBlob.
blob);
591 msg.set_signature(currentBlob.
signature);
593 msg.set_version(version);
597 "xrpl::buildValidatorListMessage(ValidatorBlobInfo) : maximum "
617 "xrpl::buildValidatorListMessage(std::map<std::size_t, "
618 "ValidatorBlobInfo>) : empty messages input");
619 protocol::TMValidatorListCollection msg;
620 auto const version = rawVersion < 2 ? 2 : rawVersion;
621 msg.set_version(version);
622 msg.set_manifest(rawManifest);
624 for (
auto const& [sequence, blobInfo] : blobInfos)
626 if (sequence <= peerSequence)
628 protocol::ValidatorBlobInfo& blob = *msg.add_blobs();
629 blob.set_blob(blobInfo.blob);
630 blob.set_signature(blobInfo.signature);
631 if (blobInfo.manifest)
632 blob.set_manifest(*blobInfo.manifest);
635 msg.blobs_size() > 0,
636 "xrpl::buildValidatorListMessage(std::map<std::size_t, "
637 "ValidatorBlobInfo>) : minimum message blobs");
648 return messages.
back().numVLs;
666 "xrpl::ValidatorList::buildValidatorListMessages : empty messages "
668 auto const& [currentSeq, currentBlob] = *blobInfos.
begin();
671 return total + m.numVLs;
673 if (messageVersion == 2 && peerSequence < maxSequence)
676 if (messages.
empty())
679 messages, peerSequence, rawVersion, rawManifest, blobInfos, maxSize);
680 if (messages.
empty())
689 return {maxSequence, numVLs};
691 if (messageVersion == 1 && peerSequence < currentSeq)
694 if (messages.
empty())
699 currentBlob.manifest ? *currentBlob.manifest : rawManifest,
702 if (messages.
empty())
711 return {currentSeq, numVLs};
739 if (messageVersion == 0u)
742 messageVersion, peerSequence, maxSequence, rawVersion, rawManifest, blobInfos, messages);
743 if (newPeerSequence != 0u)
747 "xrpl::ValidatorList::sendValidatorList : non-empty messages "
753 for (
auto const& message : messages)
757 peer.
send(message.message);
765 sent || messages.size() == 1,
766 "xrpl::ValidatorList::sendValidatorList : sent or one message");
769 if (messageVersion > 1)
771 JLOG(j.
debug()) <<
"Sent " << messages.size()
772 <<
" validator list collection(s) containing " << numVLs
773 <<
" validator list(s) for " <<
strHex(publisherKey)
774 <<
" with sequence range " << peerSequence <<
", "
775 << newPeerSequence <<
" to " << peer.
fingerprint();
781 "xrpl::ValidatorList::sendValidatorList : one validator "
783 JLOG(j.
debug()) <<
"Sent validator list for " <<
strHex(publisherKey)
784 <<
" with sequence " << newPeerSequence <<
" to "
824 auto const& current = lists.
current;
826 blobInfos[current.sequence] = {
827 .blob = current.rawBlob,
828 .signature = current.rawSignature,
829 .manifest = current.rawManifest};
830 for (
auto const& [sequence, vl] : remaining)
832 blobInfos[sequence] = {
833 .blob = vl.rawBlob, .signature = vl.rawSignature, .manifest = vl.rawManifest};
878 "xrpl::ValidatorList::broadcastBlobs : valid sequence");
883 if (!toSkip->contains(peer->id()))
885 auto const peerSequence = peer->publisherListSequence(publisherKey).value_or(0);
886 if (peerSequence < maxSequence)
888 if (blobInfos.
empty())
900 v2 ? messages2[peerSequence] : messages1,
923 auto const result =
applyLists(manifest, version, blobs, std::move(siteUri), hash);
924 auto const disposition = result.bestDisposition();
960 *result.publisherKey,
962 *pubCollection.maxSequence,
988 for (
auto const& blobInfo : blobs)
1004 stats.mergeDispositions(result);
1005 result = std::move(stats);
1020 auto& remaining = pubCollection.remaining;
1021 auto const& current = pubCollection.current;
1022 for (
auto iter = remaining.begin(); iter != remaining.end();)
1026 next == remaining.end() || next->first > iter->first,
1027 "xrpl::ValidatorList::applyLists : next is valid");
1028 if (iter->first <= current.sequence ||
1029 (next != remaining.end() && next->second.validFrom <= iter->second.validFrom))
1031 iter = remaining.erase(iter);
1041 pubCollection.fullHash =
sha512Half(pubCollection);
1043 result.
sequence = *pubCollection.maxSequence;
1060 auto iNew = publisherList.
begin();
1061 auto iOld = oldList.
begin();
1062 while (iNew != publisherList.
end() || iOld != oldList.
end())
1064 if (iOld == oldList.
end() || (iNew != publisherList.
end() && *iNew < *iOld))
1070 else if (iNew == publisherList.
end() || (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)
1101 JLOG(
j_.warn()) <<
"List for " <<
strHex(pubKey)
1102 <<
" contained untrusted validator manifest";
1109 JLOG(
j_.warn()) <<
"List for " <<
strHex(pubKey)
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] =
verify(lock, list, std::move(*m), blob, signature);
1141 JLOG(
j_.warn()) <<
"UNL manifest is signed with an unrecognized master public key";
1152 UNREACHABLE(
"xrpl::ValidatorList::applyList : invalid public key type");
1163 if (pubCollection.maxSequence &&
1170 result, pubKey, pubCollection.status, *pubCollection.maxSequence};
1178 auto const sequence = list[jss::sequence].
asUInt();
1179 auto const accepted =
1187 pubCollection.rawManifest = globalManifest;
1188 if (!pubCollection.maxSequence || sequence > *pubCollection.maxSequence)
1189 pubCollection.maxSequence = sequence;
1191 json::Value const& newList = list[jss::validators];
1193 if (accepted && pubCollection.remaining.contains(sequence))
1200 auto& publisher = pubCollection.current;
1202 oldList = std::move(pubCollection.current.list);
1204 publisher = std::move(pubCollection.remaining[sequence]);
1206 pubCollection.remaining.erase(sequence);
1209 publisher.sequence == sequence,
1210 "xrpl::ValidatorList::applyList : publisher sequence match");
1214 auto& publisher = accepted ? pubCollection.current : pubCollection.remaining[sequence];
1215 publisher.sequence = sequence;
1217 list.
isMember(jss::effective) ? list[jss::effective].
asUInt() : 0}};
1218 publisher.validUntil =
1220 publisher.siteUri = std::move(siteUri);
1221 publisher.rawBlob = blob;
1222 publisher.rawSignature = signature;
1223 publisher.rawManifest = localManifest;
1225 publisher.hash = *hash;
1231 oldList = std::move(publisherList);
1233 publisherList.
clear();
1235 for (
auto const& val : newList)
1237 if (val.isObject() && val.isMember(jss::validation_public_key) &&
1238 val[jss::validation_public_key].isString())
1241 strUnHex(val[jss::validation_public_key].asString());
1246 <<
"Invalid node identity: " << val[jss::validation_public_key].asString();
1253 if (val.isMember(jss::manifest) && val[jss::manifest].isString())
1254 manifests.
push_back(val[jss::manifest].asString());
1263 pubCollection.rawVersion =
std::max(pubCollection.rawVersion, version);
1264 if (!pubCollection.remaining.empty())
1268 pubCollection.rawVersion =
std::max(pubCollection.rawVersion, 2u);
1272 result, pubKey, pubCollection.status, *pubCollection.maxSequence};
1285 using namespace std::string_literals;
1286 using namespace boost::filesystem;
1287 using namespace boost::system::errc;
1295 boost::system::error_code ec;
1302 auto const fullPath{canonical(filename, ec)};
1306 auto size = file_size(fullPath, ec);
1307 if (!ec && (size == 0u))
1319 return fullPath.root_path() ==
"/"s ?
"file://" :
"file:///";
1349 auto const revoked = manifest.
revoked();
1365 auto const sig =
strUnHex(signature);
1371 if (!r.
parse(data, list))
1374 if (list.
isMember(jss::sequence) && list[jss::sequence].
isInt() &&
1375 list.
isMember(jss::expiration) && list[jss::expiration].
isInt() &&
1376 (!list.
isMember(jss::effective) || list[jss::effective].
isInt()) &&
1379 auto const sequence = list[jss::sequence].
asUInt();
1381 list.
isMember(jss::effective) ? list[jss::effective].
asUInt() : 0}};
1382 auto const validUntil =
1386 if (validUntil <= validFrom)
1390 if (sequence < listCollection.current.sequence)
1394 if (sequence == listCollection.current.sequence)
1398 if (validUntil <= now)
1402 if (validFrom > now)
1414 return !listCollection.maxSequence || sequence > *listCollection.maxSequence ||
1415 (!listCollection.remaining.contains(sequence) &&
1416 validFrom < listCollection.remaining.at(*listCollection.maxSequence).validFrom)
1449 return trusted(readLock, identity);
1460 return std::nullopt;
1469 return std::nullopt;
1503 "xrpl::ValidatorList::removePublisherList : valid reason input");
1508 JLOG(
j_.debug()) <<
"Removing validator list for publisher " <<
strHex(publisherKey);
1510 for (
auto const& val : iList->second.current.list)
1516 if (iVal->second <= 1)
1526 iList->second.current.list.clear();
1527 iList->second.status = reason;
1542 return count(readLock);
1552 auto const& current = collection.current;
1555 return std::nullopt;
1561 auto chainedExpiration = current.validUntil;
1562 for (
auto const& [sequence, check] : collection.remaining)
1565 if (check.validFrom <= chainedExpiration)
1567 chainedExpiration = check.validUntil;
1576 if (!res || chainedExpiration < *res)
1578 res = chainedExpiration;
1586 auto const& current = collection;
1590 if (!res || chainedExpiration < *res)
1592 res = chainedExpiration;
1619 if (
auto when =
expires(readLock))
1621 if (*when == TimeKeeper::time_point::max())
1623 x[jss::expiration] =
"never";
1624 x[jss::status] =
"active";
1632 x[jss::status] =
"active";
1636 x[jss::status] =
"expired";
1642 x[jss::status] =
"unknown";
1643 x[jss::expiration] =
"unknown";
1660 curr[jss::pubkey_publisher] =
strHex(publicKey);
1664 target[jss::uri] = publisherList.
siteUri;
1673 for (
auto const& key : publisherList.
list)
1679 auto const& current = pubCollection.current;
1680 appendList(current, curr);
1683 curr[jss::version] = pubCollection.rawVersion;
1688 for (
auto const& [sequence, future] : pubCollection.remaining)
1690 using namespace std::chrono_literals;
1694 appendList(future, r);
1698 "xrpl::ValidatorList::getJson : minimum valid from");
1700 if (remaining.
size() != 0u)
1701 curr[jss::remaining] = std::move(remaining);
1741 func(v.first,
trusted(readLock, v.first));
1752 uint256 const& hash)> func)
const
1761 plCollection.maxSequence.value_or(0) != 0,
1762 "xrpl::ValidatorList::for_each_available : nonzero maxSequence");
1764 plCollection.rawManifest,
1765 plCollection.rawVersion,
1768 plCollection.maxSequence.value_or(0),
1769 plCollection.fullHash);
1780 auto const keyBlob =
strUnHex(pubKey);
1784 JLOG(
j_.warn()) <<
"Invalid requested validator list publisher key: " << pubKey;
1810 JLOG(
j_.warn()) <<
"Using potentially unsafe quorum of " << *
minimumQuorum_
1811 <<
" as specified on the command line";
1845 auto const errorThreshold =
std::min(
1849 errorThreshold > 0,
"xrpl::ValidatorList::calculateQuorum : nonzero error threshold");
1850 if (unavailable >= errorThreshold)
1900 using namespace std::chrono_literals;
1914 auto& remaining = collection.remaining;
1915 auto const firstIter = remaining.begin();
1916 auto iter = firstIter;
1917 if (iter != remaining.end() && iter->second.validFrom <= closeTime)
1921 next != remaining.end() && next->second.validFrom <= closeTime;
1926 "xrpl::ValidatorList::updateTrusted : sequential "
1930 iter != remaining.end(),
1931 "xrpl::ValidatorList::updateTrusted : non-end of "
1935 auto sequence = iter->first;
1936 auto& candidate = iter->second;
1937 auto& current = collection.current;
1939 candidate.validFrom <= closeTime,
1940 "xrpl::ValidatorList::updateTrusted : maximum time");
1942 auto const oldList = current.list;
1943 current = std::move(candidate);
1947 current.sequence == sequence,
1948 "xrpl::ValidatorList::updateTrusted : sequence match");
1952 if (current.validUntil <= closeTime)
1953 current.list.clear();
1962 broadcastBlobs(pubKey, collection, sequence, current.hash, overlay, hashRouter,
j_);
1965 remaining.erase(firstIter,
std::next(iter));
1972 collection.current.validUntil <= closeTime)
2000 "xrpl::ValidatorList::updateTrusted : count meets threshold");
2014 if (!trustChanges.
added.empty() || !trustChanges.
removed.empty())
2023 XRPL_ASSERT(signingKey,
"xrpl::ValidatorList::updateTrusted : found signing key");
2030 <<
" listed validators eligible for inclusion in the trusted set";
2033 auto effectiveUnlSize = unlSize;
2034 auto seenSize = seenValidators.
size();
2047 for (
auto const& nid : seenValidators)
2055 JLOG(
j_.debug()) <<
"Using quorum of " <<
quorum_ <<
" for new set of " << unlSize
2056 <<
" trusted validators (" << trustChanges.
added.size() <<
" added, "
2057 << trustChanges.
removed.size() <<
" removed)";
2061 JLOG(
j_.warn()) <<
"New quorum of " <<
quorum_
2062 <<
" exceeds the number of trusted validators (" << unlSize <<
")";
2071 return trustChanges;
2106 auto ret = std::move(validations);
2114 [&](
auto const& v) ->
bool {
2115 if (
auto const masterKey =
getTrustedKey(readLock, v->getSignerPublic());
NetClock::duration duration
NetClock::time_point time_point
A generic endpoint for log messages.
Stream trace() const
Severity stream access functions.
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 asString() const
Returns the unquoted string value.
bool isMember(char const *key) const
Return true if the object has a member named key.
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.
static std::size_t totalSize(::google::protobuf::Message const &message)
std::chrono::time_point< NetClock > time_point
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
static std::size_t size() noexcept
An immutable linear range of bytes.
Manages various times used by the server.
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)
std::scoped_lock< decltype(mutex_)> scoped_lock
static constexpr std::size_t kMaxSupportedBlobs
std::pair< ListDisposition, std::optional< PublicKey > > verify(scoped_lock const &, json::Value &list, Manifest manifest, std::string const &blob, std::string const &signature)
Check response for trusted valid published list.
std::shared_lock< decltype(mutex_)> shared_lock
hash_set< PublicKey > trustedMasterKeys_
static std::string const kFilePrefix
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, scoped_lock const &)
Apply published list of public keys.
void forEachListed(std::function< void(PublicKey const &, bool)> func) const
Invokes the callback once for every listed validation public key.
bool trustedPublisher(PublicKey const &identity) const
Returns true if public key is a trusted publisher.
bool removePublisherList(scoped_lock const &, PublicKey const &publisherKey, PublisherStatus reason)
Stop trusting publisher's list of keys.
hash_set< PublicKey > trustedSigningKeys_
std::size_t calculateQuorum(std::size_t unlSize, std::size_t effectiveUnlSize, std::size_t seenSize)
Return quorum for trusted validator set.
ValidatorList(ManifestCache &validatorManifests, ManifestCache &publisherManifests, TimeKeeper &timeKeeper, std::string const &databasePath, beast::Journal j, std::optional< std::size_t > minimumQuorum=std::nullopt)
std::vector< std::string > loadLists()
hash_set< PublicKey > getTrustedMasterKeys() const
get the trusted master public keys
std::optional< PublicKey > localPubKey_
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...
std::atomic< std::size_t > quorum_
json::Value getJson() const
Return a JSON representation of the state of the validator list.
void forEachAvailable(std::function< void(std::string const &manifest, std::uint32_t version, std::map< std::size_t, ValidatorBlobInfo > const &blobInfos, PublicKey const &pubKey, std::size_t maxSequence, uint256 const &hash)> func) const
Invokes the callback once for every available publisher list's raw data members.
void cacheValidatorFile(scoped_lock const &lock, PublicKey const &pubKey) const
Write a JSON UNL to a cache file.
std::optional< json::Value > getAvailable(std::string_view pubKey, std::optional< std::uint32_t > forceVersion={})
Returns the current valid list for the given publisher key, if available, as a Json object.
PublisherList localPublisherList_
boost::filesystem::path getCacheFileName(scoped_lock const &, PublicKey const &pubKey) const
Get the filename used for caching UNLs.
TrustChanges updateTrusted(hash_set< NodeID > const &seenValidators, NetClock::time_point closeTime, NetworkOPs &ops, Overlay &overlay, HashRouter &hashRouter)
Update trusted nodes.
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.
void updatePublisherList(PublicKey const &pubKey, PublisherList const ¤t, std::vector< PublicKey > const &oldList, scoped_lock const &)
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.
std::optional< PublicKey > getListedKey(PublicKey const &identity) const
Returns listed master public if public key is included on any lists.
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=kMaximumMessageSize)
hash_set< PublicKey > getNegativeUNL() const
get the master public keys of Negative UNL validators
std::optional< std::size_t > minimumQuorum_
ManifestCache & publisherManifests_
hash_map< PublicKey, std::size_t > keyListings_
std::size_t getListThreshold() const
get the validator list threshold
std::optional< TimeKeeper::time_point > expires() const
Return the time when the validator list will expire.
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,...
static void buildBlobInfos(std::map< std::size_t, ValidatorBlobInfo > &blobInfos, PublisherListCollection const &lists)
ManifestCache & validatorManifests_
hash_set< PublicKey > negativeUNL_
std::size_t listThreshold_
void setNegativeUNL(hash_set< PublicKey > const &negUnl)
set the Negative UNL with validators' master public keys
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.
std::vector< std::shared_ptr< STValidation > > negativeUNLFilter(std::vector< std::shared_ptr< STValidation > > &&validations) const
Remove validations that are from validators on the negative UNL.
static constexpr std::uint32_t kSupportedListVersions[]
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...
bool trusted(PublicKey const &identity) const
Returns true if public key is trusted.
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)
@ Array
array value (ordered list)
@ Object
object value (collection of name/value pairs).
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
constexpr std::size_t kMaximumMessageSize
std::string base64Decode(std::string_view data)
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::optional< AccountID > parseBase58(std::string const &s)
Parse AccountID from checked, base58 string.
std::string strHex(FwdIt begin, FwdIt end)
@ UnsupportedVersion
List version is not supported.
@ Expired
List is expired, but has the largest non-pending sequence seen so far.
@ SameSequence
Same sequence as current list.
@ KnownSequence
Future sequence already seen.
@ Pending
List will be valid in the future.
@ Invalid
Invalid format or signature.
@ Untrusted
List signed by untrusted publisher key.
@ Stale
Trusted publisher key, but seq is too old.
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::unordered_set< Value, Hash, Pred, Allocator > hash_set
std::string to_string(BaseUInt< Bits, Tag > const &a)
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)
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::enable_if_t< std::is_same_v< T, char >||std::is_same_v< T, unsigned char >, Slice > makeSlice(std::array< T, N > const &a)
@ Accepted
Manifest is valid.
@ Invalid
Timely, but invalid signature.
static bool revoked(std::uint32_t sequence)
Returns true if manifest revokes master key.
PublicKey masterKey
The master key associated with this manifest.
std::optional< PublicKey > signingKey
The ephemeral key associated with this manifest.
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::shared_ptr< Message > message
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
std::vector< std::string > manifests