xrpld
Loading...
Searching...
No Matches
ValidatorList.h
1#pragma once
2
3#include <xrpld/core/TimeKeeper.h>
4#include <xrpld/overlay/Message.h>
5
6#include <xrpl/basics/UnorderedContainers.h>
7#include <xrpl/basics/base_uint.h>
8#include <xrpl/basics/chrono.h>
9#include <xrpl/beast/utility/Journal.h>
10#include <xrpl/json/json_value.h>
11#include <xrpl/protocol/PublicKey.h>
12#include <xrpl/protocol/UintTypes.h>
13#include <xrpl/server/Manifest.h>
14
15#include <boost/thread/shared_mutex.hpp>
16
17#include <atomic>
18#include <cstddef>
19#include <cstdint>
20#include <filesystem>
21#include <functional>
22#include <map>
23#include <memory>
24#include <mutex>
25#include <optional>
26#include <shared_mutex>
27#include <string>
28#include <string_view>
29#include <utility>
30#include <vector>
31
32namespace protocol {
33class TMValidatorListCollection;
34} // namespace protocol
35
36namespace xrpl {
37
38class Overlay;
39class HashRouter;
40class Message;
41class NetworkOPs;
42class Peer;
43class STValidation;
44
45/* Entries in this enum are ordered by "desirability".
46 The "better" dispositions have lower values than the
47 "worse" dispositions */
94
95/* Entries in this enum are ordered by "desirability".
96 The "better" dispositions have lower values than the
97 "worse" dispositions */
98enum class PublisherStatus {
99 // Publisher has provided a valid file
101
102 // Current list is expired without replacement
104
105 // No file seen yet
107
108 // Publisher has revoked their manifest key
110
111};
112
114to_string(ListDisposition disposition);
115
126
131{
132 // base-64 encoded JSON containing the validator list.
134 // hex-encoded signature of the blob using the publisher's signing key
136 // base-64 or hex-encoded manifest containing the publisher's master and
137 // signing public keys
139};
140
187{
189 {
190 explicit PublisherList() = default;
191
198 // base-64 encoded JSON containing the validator list.
200 // hex-encoded signature of the blob using the publisher's signing key
202 // base-64 or hex-encoded manifest containing the publisher's master and
203 // signing public keys
206 };
207
209 {
211 /*
212 The `current` VL is the one which
213 1. Has the largest sequence number that
214 2. Has ever been effective (the effective date is absent or in the
215 past).
216 If this VL has expired, all VLs with previous sequence numbers
217 will also be considered expired, and thus there will be no valid VL
218 until one with a larger sequence number becomes effective. This is to
219 prevent allowing old VLs to reactivate.
220 */
222 /*
223 The `remaining` list holds any relevant VLs which have a larger sequence
224 number than current. By definition they will all have an effective date
225 in the future. Relevancy will be determined by sorting the VLs by
226 sequence number, then iterating over the list and removing any VLs for
227 which the following VL (ignoring gaps) has the same or earlier effective
228 date.
229 */
232 // The hash of the full set if sent in a single message
236 };
237
246
249
250 // Published lists stored by publisher master public key
252
253 // Listed master public keys with the number of lists they appear on
255
256 // The current list of trusted master keys
258
259 // Minimum number of lists on which a trusted validator must appear on
261
262 // The current list of trusted signing keys. For those validators using
263 // a manifest, the signing key is the ephemeral key. For the ones using
264 // a seed, the signing key is the same as the master key.
266
268
269 // The below variable contains the Publisher list specified in the local
270 // config file under the title of [validators]. This list is not associated
271 // with the masterKey of any publisher.
272
273 // Apropos PublisherListCollection fields, localPublisherList does not
274 // have any "remaining" manifests. It is assumed to be perennially
275 // "available". The "validUntil" field is set to the highest possible
276 // value of the field, hence this list is always valid.
278
279 // The master public keys of the current negative UNL
281
282 // Currently supported versions of publisher list format
283 static constexpr std::uint32_t kSupportedListVersions[]{1, 2};
284 // In the initial release, to prevent potential abuse and attacks, any VL
285 // collection with more than 5 entries will be considered malformed.
286 static constexpr std::size_t kMaxSupportedBlobs = 5;
287 // Prefix of the file name used to store cache files.
289
290public:
292 ManifestCache& validatorManifests,
293 ManifestCache& publisherManifests,
294 TimeKeeper& timeKeeper,
295 std::string const& databasePath,
297 std::optional<std::size_t> minimumQuorum = std::nullopt);
298 ~ValidatorList() = default;
299
307 {
308 explicit PublisherListStats() = default;
311
312 [[nodiscard]] ListDisposition
313 bestDisposition() const;
314 [[nodiscard]] ListDisposition
315 worstDisposition() const;
316 void
318
319 // Tracks the dispositions of each processed list and how many times it
320 // occurred
325 };
326
338
357 bool
358 load(
359 std::optional<PublicKey> const& localSigningKey,
360 std::vector<std::string> const& configKeys,
361 std::vector<std::string> const& publisherKeys,
362 std::optional<std::size_t> listThreshold = {});
363
371 parseBlobs(std::uint32_t version, json::Value const& body);
372
374 parseBlobs(protocol::TMValidatorListCollection const& body);
375
376 static void
378 Peer& peer,
379 std::uint64_t peerSequence,
380 PublicKey const& publisherKey,
381 std::size_t maxSequence,
382 std::uint32_t rawVersion,
383 std::string const& rawManifest,
385 HashRouter& hashRouter,
387
388 [[nodiscard]] static std::pair<std::size_t, std::size_t>
390 std::uint64_t peerSequence,
391 std::size_t maxSequence,
392 std::uint32_t rawVersion,
393 std::string const& rawManifest,
397
428 PublisherListStats
430 std::string const& manifest,
431 std::uint32_t version,
433 std::string siteUri,
434 uint256 const& hash,
435 Overlay& overlay,
436 HashRouter& hashRouter,
437 NetworkOPs& networkOPs);
438
460 PublisherListStats
462 std::string const& manifest,
463 std::uint32_t version,
465 std::string siteUri,
466 std::optional<uint256> const& hash = {});
467
479 loadLists();
480
497 TrustChanges
499 hash_set<NodeID> const& seenValidators,
500 NetClock::time_point closeTime,
501 NetworkOPs& ops,
502 Overlay& overlay,
503 HashRouter& hashRouter);
504
520 quorum() const
521 {
522 return quorum_;
523 }
524
534 bool
535 trusted(PublicKey const& identity) const;
536
546 bool
547 listed(PublicKey const& identity) const;
548
561 getTrustedKey(PublicKey const& identity) const;
562
575 getListedKey(PublicKey const& identity) const;
576
586 bool
587 trustedPublisher(PublicKey const& identity) const;
588
598 localPublicKey() const;
599
616 void
617 forEachListed(std::function<void(PublicKey const&, bool)> func) const;
618
647 void
649 std::function<void(
650 std::string const& manifest,
651 std::uint32_t version,
653 PublicKey const& pubKey,
654 std::size_t maxSequence,
655 uint256 const& hash)> func) const;
656
663
668 count() const;
669
681 expires() const;
682
690 getJson() const;
691
700 {
701 shared_lock const readLock{mutex_};
703 }
704
710 getTrustedMasterKeys() const;
711
717 getListThreshold() const;
718
724 getNegativeUNL() const;
725
730 void
731 setNegativeUNL(hash_set<PublicKey> const& negUnl);
732
741
742private:
747 count(shared_lock const&) const;
748
758 bool
759 trusted(shared_lock const&, PublicKey const& identity) const;
760
773 getTrustedKey(shared_lock const&, PublicKey const& identity) const;
774
786 expires(shared_lock const&) const;
787
811 PublisherListStats
812 applyList(
813 std::string const& globalManifest,
814 std::optional<std::string> const& localManifest,
815 std::string const& blob,
816 std::string const& signature,
817 std::uint32_t version,
818 std::string siteUri,
819 std::optional<uint256> const& hash,
820 scoped_lock const&);
821
822 // This function updates the keyListings_ counts for all the trusted
823 // master keys
824 void
826 PublicKey const& pubKey,
827 PublisherList const& current,
828 std::vector<PublicKey> const& oldList,
829 scoped_lock const&);
830
831 static void
834 PublisherListCollection const& lists);
835
837 buildBlobInfos(PublisherListCollection const& lists);
838
839 static void
841 PublicKey const& publisherKey,
842 PublisherListCollection const& lists,
843 std::size_t maxSequence,
844 uint256 const& hash,
845 Overlay& overlay,
846 HashRouter& hashRouter,
848
849 static void
851 Peer& peer,
852 std::uint64_t peerSequence,
853 PublicKey const& publisherKey,
854 std::size_t maxSequence,
855 std::uint32_t rawVersion,
856 std::string const& rawManifest,
859 HashRouter& hashRouter,
861
866 getCacheFileName(scoped_lock const&, PublicKey const& pubKey) const;
867
872 static json::Value
874 std::string const& pubKey,
875 PublisherListCollection const& pubCollection,
877
882 static json::Value
884 std::string const& pubKey,
885 PublisherListCollection const& pubCollection,
886 std::optional<std::uint32_t> forceVersion,
888
889 template <class Hasher>
890 friend void
896
900 void
901 cacheValidatorFile(scoped_lock const& lock, PublicKey const& pubKey) const;
902
913 verify(
914 scoped_lock const&,
915 json::Value& list,
916 Manifest manifest,
917 std::string const& blob,
918 std::string const& signature);
919
931 bool
932 removePublisherList(scoped_lock const&, PublicKey const& publisherKey, PublisherStatus reason);
933
946 calculateQuorum(std::size_t unlSize, std::size_t effectiveUnlSize, std::size_t seenSize);
947};
948
949// hashing helpers
950template <class Hasher>
951void
952hash_append(Hasher& h, ValidatorBlobInfo const& blobInfo)
953{
954 using beast::hash_append;
955 hash_append(h, blobInfo.blob, blobInfo.signature);
956 if (blobInfo.manifest)
957 {
958 hash_append(h, *blobInfo.manifest);
959 }
960}
961
962template <class Hasher>
963void
965{
966 for (auto const& item : blobs)
967 hash_append(h, item);
968}
969
970template <class Hasher>
971void
973{
974 for (auto const& [_, item] : blobs)
975 {
976 (void)_;
977 hash_append(h, item);
978 }
979}
980
981} // namespace xrpl
982
983namespace protocol {
984
985template <class Hasher>
986void
987hash_append(Hasher& h, TMValidatorListCollection const& msg)
988{
989 using beast::hash_append;
990 hash_append(h, msg.manifest(), xrpl::ValidatorList::parseBlobs(msg), msg.version());
991}
992
993} // namespace protocol
NetClock::time_point time_point
A generic endpoint for log messages.
Definition Journal.h:44
Represents a JSON value.
Definition json_value.h:117
Routing table for objects identified by hash.
Definition HashRouter.h:86
Remembers manifests with the highest sequence number.
Definition Manifest.h:374
std::chrono::time_point< NetClock > time_point
Definition chrono.h:48
Provides server functionality for clients.
Definition NetworkOPs.h:82
Manages the set of connected peers.
Definition Overlay.h:38
Represents a peer connection in the overlay.
A public key.
Definition PublicKey.h:53
Manages various times used by the server.
Definition TimeKeeper.h:15
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)
TimeKeeper & timeKeeper_
std::scoped_lock< decltype(mutex_)> scoped_lock
std::filesystem::path getCacheFileName(scoped_lock const &, PublicKey const &pubKey) const
Get the filename used for caching UNLs.
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)
~ValidatorList()=default
std::vector< std::string > loadLists()
Attempt to read previously stored list files.
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::pair< std::size_t const, hash_set< PublicKey > > QuorumKeys
QuorumKeys getQuorumKeys() const
Get the quorum and all of the trusted keys.
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_
beast::Journal const j_
TrustChanges updateTrusted(hash_set< NodeID > const &seenValidators, NetClock::time_point closeTime, NetworkOPs &ops, Overlay &overlay, HashRouter &hashRouter)
Update trusted nodes.
std::shared_mutex mutex_
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 &current, 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::size_t quorum() const
Get quorum value for current trusted key set.
std::optional< PublicKey > getListedKey(PublicKey const &identity) const
Returns listed master public if public key is included on any lists.
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)
static std::pair< std::size_t, std::size_t > buildValidatorListMessages(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)
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::filesystem::path const dataPath_
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_
friend void hash_append(Hasher &h, PublisherListCollection pl)
void hash_append(Hasher &h, T const &t) noexcept
Logically concatenate input data to a Hasher.
void hash_append(Hasher &h, TMValidatorListCollection const &msg)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
constexpr std::size_t kMaximumMessageSize
Definition Message.h:22
ListDisposition
@ UnsupportedVersion
List version is not supported.
@ SameSequence
Same sequence as current list.
@ KnownSequence
Future sequence already seen.
@ Pending
List will be valid in the future.
@ Untrusted
List signed by untrusted publisher key.
std::unordered_set< Value, Hash, Pred, Allocator > hash_set
std::string to_string(BaseUInt< Bits, Tag > const &a)
Definition base_uint.h:651
@ Stale
Not current or was older than current from this node.
@ Expired
Consensus time limit has hard-expired.
@ Accepted
We have accepted a new last closed ledger and are waiting on a call to startRound to begin the next c...
PublisherStatus
std::unordered_map< Key, Value, Hash, Pred, Allocator > hash_map
void hash_append(Hasher &h, Slice const &v)
Definition Slice.h:194
BaseUInt< 256 > uint256
Definition base_uint.h:580
@ Invalid
Timely, but invalid signature.
Definition Manifest.h:329
hash_set< NodeID > added
TrustChanges()=default
hash_set< NodeID > removed
Used to represent the information stored in the blobs_v2 Json array.
std::optional< std::string > manifest
std::shared_ptr< Message > message
std::optional< std::size_t > maxSequence
std::map< std::size_t, PublisherList > remaining
void mergeDispositions(PublisherListStats const &src)
std::optional< PublicKey > publisherKey
std::map< ListDisposition, std::size_t > dispositions
std::vector< PublicKey > list
TimeKeeper::time_point validFrom
TimeKeeper::time_point validUntil
std::vector< std::string > manifests
std::optional< std::string > rawManifest