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/Log.h>
7#include <xrpl/basics/UnorderedContainers.h>
8#include <xrpl/crypto/csprng.h>
9#include <xrpl/json/json_value.h>
10#include <xrpl/protocol/PublicKey.h>
11#include <xrpl/server/Manifest.h>
12
13#include <boost/thread/shared_mutex.hpp>
14
15#include <mutex>
16#include <shared_mutex>
17
18namespace protocol {
19class TMValidatorList;
20class TMValidatorListCollection;
21} // namespace protocol
22
23namespace xrpl {
24
25class Overlay;
26class HashRouter;
27class Message;
28class NetworkOPs;
29class Peer;
30class STValidation;
31
32/* Entries in this enum are ordered by "desirability".
33 The "better" dispositions have lower values than the
34 "worse" dispositions */
63
64/* Entries in this enum are ordered by "desirability".
65 The "better" dispositions have lower values than the
66 "worse" dispositions */
67enum class PublisherStatus {
68 // Publisher has provided a valid file
70
71 // Current list is expired without replacement
73
74 // No file seen yet
76
77 // Publisher has revoked their manifest key
79
80};
81
83to_string(ListDisposition disposition);
84
94
97{
98 // base-64 encoded JSON containing the validator list.
100 // hex-encoded signature of the blob using the publisher's signing key
102 // base-64 or hex-encoded manifest containing the publisher's master and
103 // signing public keys
105};
106
153{
155 {
156 explicit PublisherList() = default;
157
164 // base-64 encoded JSON containing the validator list.
166 // hex-encoded signature of the blob using the publisher's signing key
168 // base-64 or hex-encoded manifest containing the publisher's master and
169 // signing public keys
172 };
173
175 {
177 /*
178 The `current` VL is the one which
179 1. Has the largest sequence number that
180 2. Has ever been effective (the effective date is absent or in the
181 past).
182 If this VL has expired, all VLs with previous sequence numbers
183 will also be considered expired, and thus there will be no valid VL
184 until one with a larger sequence number becomes effective. This is to
185 prevent allowing old VLs to reactivate.
186 */
188 /*
189 The `remaining` list holds any relevant VLs which have a larger sequence
190 number than current. By definition they will all have an effective date
191 in the future. Relevancy will be determined by sorting the VLs by
192 sequence number, then iterating over the list and removing any VLs for
193 which the following VL (ignoring gaps) has the same or earlier effective
194 date.
195 */
198 // The hash of the full set if sent in a single message
202 };
203
207 boost::filesystem::path const dataPath_;
212
215
216 // Published lists stored by publisher master public key
218
219 // Listed master public keys with the number of lists they appear on
221
222 // The current list of trusted master keys
224
225 // Minimum number of lists on which a trusted validator must appear on
227
228 // The current list of trusted signing keys. For those validators using
229 // a manifest, the signing key is the ephemeral key. For the ones using
230 // a seed, the signing key is the same as the master key.
232
234
235 // The below variable contains the Publisher list specified in the local
236 // config file under the title of [validators]. This list is not associated
237 // with the masterKey of any publisher.
238
239 // Apropos PublisherListCollection fields, localPublisherList does not
240 // have any "remaining" manifests. It is assumed to be perennially
241 // "available". The "validUntil" field is set to the highest possible
242 // value of the field, hence this list is always valid.
244
245 // The master public keys of the current negative UNL
247
248 // Currently supported versions of publisher list format
249 static constexpr std::uint32_t kSupportedListVersions[]{1, 2};
250 // In the initial release, to prevent potential abuse and attacks, any VL
251 // collection with more than 5 entries will be considered malformed.
252 static constexpr std::size_t kMaxSupportedBlobs = 5;
253 // Prefix of the file name used to store cache files.
255
256public:
258 ManifestCache& validatorManifests,
259 ManifestCache& publisherManifests,
260 TimeKeeper& timeKeeper,
261 std::string const& databasePath,
263 std::optional<std::size_t> minimumQuorum = std::nullopt);
264 ~ValidatorList() = default;
265
272 {
273 explicit PublisherListStats() = default;
276
277 [[nodiscard]] ListDisposition
278 bestDisposition() const;
279 [[nodiscard]] ListDisposition
280 worstDisposition() const;
281 void
283
284 // Tracks the dispositions of each processed list and how many times it
285 // occurred
290 };
291
303
321 bool
322 load(
323 std::optional<PublicKey> const& localSigningKey,
324 std::vector<std::string> const& configKeys,
325 std::vector<std::string> const& publisherKeys,
326 std::optional<std::size_t> listThreshold = {});
327
334 parseBlobs(std::uint32_t version, json::Value const& body);
335
337 parseBlobs(protocol::TMValidatorList const& body);
338
340 parseBlobs(protocol::TMValidatorListCollection const& body);
341
342 static void
344 Peer& peer,
345 std::uint64_t peerSequence,
346 PublicKey const& publisherKey,
347 std::size_t maxSequence,
348 std::uint32_t rawVersion,
349 std::string const& rawManifest,
351 HashRouter& hashRouter,
353
354 [[nodiscard]] static std::pair<std::size_t, std::size_t>
356 std::size_t messageVersion,
357 std::uint64_t peerSequence,
358 std::size_t maxSequence,
359 std::uint32_t rawVersion,
360 std::string const& rawManifest,
364
394 PublisherListStats
396 std::string const& manifest,
397 std::uint32_t version,
399 std::string siteUri,
400 uint256 const& hash,
401 Overlay& overlay,
402 HashRouter& hashRouter,
403 NetworkOPs& networkOPs);
404
425 PublisherListStats
427 std::string const& manifest,
428 std::uint32_t version,
430 std::string siteUri,
431 std::optional<uint256> const& hash = {});
432
433 /* Attempt to read previously stored list files. Expected to only be
434 called when loading from URL fails.
435
436 @return A list of valid file:// URLs, if any.
437
438 @par Thread Safety
439
440 May be called concurrently
441 */
443 loadLists();
444
460 TrustChanges
462 hash_set<NodeID> const& seenValidators,
463 NetClock::time_point closeTime,
464 NetworkOPs& ops,
465 Overlay& overlay,
466 HashRouter& hashRouter);
467
482 quorum() const
483 {
484 return quorum_;
485 }
486
495 bool
496 trusted(PublicKey const& identity) const;
497
506 bool
507 listed(PublicKey const& identity) const;
508
520 getTrustedKey(PublicKey const& identity) const;
521
533 getListedKey(PublicKey const& identity) const;
534
543 bool
544 trustedPublisher(PublicKey const& identity) const;
545
554 localPublicKey() const;
555
571 void
572 forEachListed(std::function<void(PublicKey const&, bool)> func) const;
573
601 void
603 std::function<void(
604 std::string const& manifest,
605 std::uint32_t version,
607 PublicKey const& pubKey,
608 std::size_t maxSequence,
609 uint256 const& hash)> func) const;
610
616
619 count() const;
620
631 expires() const;
632
639 getJson() const;
640
648 {
649 shared_lock const readLock{mutex_};
651 }
652
658 getTrustedMasterKeys() const;
659
665 getListThreshold() const;
666
672 getNegativeUNL() const;
673
678 void
679 setNegativeUNL(hash_set<PublicKey> const& negUnl);
680
689
690private:
693 count(shared_lock const&) const;
694
703 bool
704 trusted(shared_lock const&, PublicKey const& identity) const;
705
717 getTrustedKey(shared_lock const&, PublicKey const& identity) const;
718
729 expires(shared_lock const&) const;
730
753 PublisherListStats
754 applyList(
755 std::string const& globalManifest,
756 std::optional<std::string> const& localManifest,
757 std::string const& blob,
758 std::string const& signature,
759 std::uint32_t version,
760 std::string siteUri,
761 std::optional<uint256> const& hash,
762 scoped_lock const&);
763
764 // This function updates the keyListings_ counts for all the trusted
765 // master keys
766 void
768 PublicKey const& pubKey,
769 PublisherList const& current,
770 std::vector<PublicKey> const& oldList,
771 scoped_lock const&);
772
773 static void
776 PublisherListCollection const& lists);
777
779 buildBlobInfos(PublisherListCollection const& lists);
780
781 static void
783 PublicKey const& publisherKey,
784 PublisherListCollection const& lists,
785 std::size_t maxSequence,
786 uint256 const& hash,
787 Overlay& overlay,
788 HashRouter& hashRouter,
790
791 static void
793 Peer& peer,
794 std::uint64_t peerSequence,
795 PublicKey const& publisherKey,
796 std::size_t maxSequence,
797 std::uint32_t rawVersion,
798 std::string const& rawManifest,
801 HashRouter& hashRouter,
803
806 boost::filesystem::path
807 getCacheFileName(scoped_lock const&, PublicKey const& pubKey) const;
808
812 static json::Value
814 std::string const& pubKey,
815 PublisherListCollection const& pubCollection,
817
821 static json::Value
823 std::string const& pubKey,
824 PublisherListCollection const& pubCollection,
825 std::optional<std::uint32_t> forceVersion,
827
828 template <class Hasher>
829 friend void
835
838 void
839 cacheValidatorFile(scoped_lock const& lock, PublicKey const& pubKey) const;
840
850 verify(
851 scoped_lock const&,
852 json::Value& list,
853 Manifest manifest,
854 std::string const& blob,
855 std::string const& signature);
856
867 bool
868 removePublisherList(scoped_lock const&, PublicKey const& publisherKey, PublisherStatus reason);
869
881 calculateQuorum(std::size_t unlSize, std::size_t effectiveUnlSize, std::size_t seenSize);
882};
883
884// hashing helpers
885template <class Hasher>
886void
887hash_append(Hasher& h, ValidatorBlobInfo const& blobInfo)
888{
889 using beast::hash_append;
890 hash_append(h, blobInfo.blob, blobInfo.signature);
891 if (blobInfo.manifest)
892 {
893 hash_append(h, *blobInfo.manifest);
894 }
895}
896
897template <class Hasher>
898void
900{
901 for (auto const& item : blobs)
902 hash_append(h, item);
903}
904
905template <class Hasher>
906void
908{
909 for (auto const& [_, item] : blobs)
910 {
911 (void)_;
912 hash_append(h, item);
913 }
914}
915
916} // namespace xrpl
917
918namespace protocol {
919
920template <class Hasher>
921void
922hash_append(Hasher& h, TMValidatorList const& msg)
923{
924 using beast::hash_append;
925 hash_append(h, msg.manifest(), msg.blob(), msg.signature(), msg.version());
926}
927
928template <class Hasher>
929void
930hash_append(Hasher& h, TMValidatorListCollection const& msg)
931{
932 using beast::hash_append;
933 hash_append(h, msg.manifest(), xrpl::ValidatorList::parseBlobs(msg), msg.version());
934}
935
936} // namespace protocol
NetClock::time_point time_point
A generic endpoint for log messages.
Definition Journal.h:38
Represents a JSON value.
Definition json_value.h:130
Routing table for objects identified by hash.
Definition HashRouter.h:77
Remembers manifests with the highest sequence number.
Definition Manifest.h:236
std::chrono::time_point< NetClock > time_point
Definition chrono.h:46
Provides server functionality for clients.
Definition NetworkOPs.h:71
Manages the set of connected peers.
Definition Overlay.h:25
Represents a peer connection in the overlay.
A public key.
Definition PublicKey.h:42
Manages various times used by the server.
Definition TimeKeeper.h:12
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
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()
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_
boost::filesystem::path getCacheFileName(scoped_lock const &, PublicKey const &pubKey) const
Get the filename used for caching UNLs.
beast::Journal const j_
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_
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.
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_
friend void hash_append(Hasher &h, PublisherListCollection pl)
std::enable_if_t< IsContiguouslyHashable< T, Hasher >::value > hash_append(Hasher &h, T const &t) noexcept
Logically concatenate input data to a Hasher.
void hash_append(Hasher &h, TMValidatorList 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:14
ListDisposition
@ 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.
@ 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:633
PublisherStatus
std::unordered_map< Key, Value, Hash, Pred, Allocator > hash_map
void hash_append(Hasher &h, Slice const &v)
Definition Slice.h:175
BaseUInt< 256 > uint256
Definition base_uint.h:562
@ Accepted
Manifest is valid.
Definition Manifest.h:197
@ Invalid
Timely, but invalid signature.
Definition Manifest.h:209
@ Stale
Sequence is too old.
Definition Manifest.h:200
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