20 #include <ripple/app/misc/ValidatorList.h>
21 #include <ripple/app/misc/HashRouter.h>
22 #include <ripple/basics/base64.h>
23 #include <ripple/basics/FileUtilities.h>
24 #include <ripple/basics/Slice.h>
25 #include <ripple/basics/StringUtilities.h>
26 #include <ripple/json/json_reader.h>
27 #include <ripple/overlay/Overlay.h>
28 #include <ripple/protocol/jss.h>
29 #include <ripple/protocol/messages.h>
30 #include <boost/regex.hpp>
32 #include <date/date.h>
48 return "same_sequence";
50 return "unsupported_version";
69 boost::optional<std::size_t> minimumQuorum)
70 : validatorManifests_ (validatorManifests)
71 , publisherManifests_ (publisherManifests)
72 , timeKeeper_ (timeKeeper)
73 , dataPath_(databasePath)
75 , quorum_ (minimumQuorum.value_or(1))
76 , minimumQuorum_ (minimumQuorum)
86 static boost::regex
const re (
101 "Loading configured trusted validator list publisher keys";
104 for (
auto key : publisherKeys)
107 "Processing '" << key <<
"'";
114 "Invalid validator list publisher key: " << key;
123 "Configured validator list publisher key is revoked: " << key;
130 "Duplicate validator list publisher key: " << key;
139 "Loaded " <<
count <<
" keys";
148 "Loading configured validator keys";
152 for (
auto const& n : configKeys)
155 "Processing '" << n <<
"'";
159 if (!boost::regex_match (n, match, re))
162 "Malformed entry: '" << n <<
"'";
166 auto const id = parseBase58<PublicKey>(
171 JLOG (
j_.
error()) <<
"Invalid node identity: " << match[1];
182 JLOG (
j_.
warn()) <<
"Duplicate node identity: " << match[1];
186 std::piecewise_construct,
191 it.first->second.expiration = TimeKeeper::time_point::max();
192 it.first->second.list.emplace_back(std::move(*
id));
193 it.first->second.available =
true;
198 "Loaded " <<
count <<
" entries";
203 boost::filesystem::path
216 boost::filesystem::path
const filename =
219 boost::system::error_code ec;
224 value[
"blob"] = publisher.
rawBlob;
234 "Problem writing " <<
255 version, std::move(siteUri), hash);
256 auto const disposition = result.disposition;
263 assert(result.available && result.publisherKey && result.sequence);
268 protocol::TMValidatorList msg;
271 msg.set_signature(signature);
272 msg.set_version(version);
274 auto const& publisherKey = *result.publisherKey;
275 auto const sequence = *result.sequence;
280 std::make_shared<Message>(msg, protocol::mtVALIDATORLIST);
283 if (toSkip->count(peer->id()) == 0 &&
284 peer->supportsFeature(
286 peer->publisherListSequence(publisherKey) < sequence)
291 <<
"Sent validator list for " <<
strHex(publisherKey)
292 <<
" with sequence " << sequence <<
" to "
293 << peer->getRemoteAddress().to_string() <<
" ("
294 << peer->id() <<
")";
297 peer->setPublisherListSequence(publisherKey, sequence);
313 boost::optional<uint256>
const& hash)
315 using namespace std::string_literals;
324 auto const result =
verify (list, pubKey,
manifest, blob, signature);
334 publisher.available, publisher.sequence };
342 publisher.available =
true;
343 publisher.sequence = list[
"sequence"].
asUInt ();
346 publisher.siteUri = std::move(siteUri);
348 publisher.rawBlob = blob;
349 publisher.rawSignature = signature;
350 publisher.rawVersion = version;
352 publisher.hash = *hash;
356 publisher.available, publisher.sequence };
359 publisherList.
clear ();
362 for (
auto const& val : newList)
364 if (val.isObject() &&
365 val.isMember (
"validation_public_key") &&
366 val[
"validation_public_key"].isString ())
368 boost::optional<Blob>
const ret =
strUnHex(val[
"validation_public_key"].asString());
373 "Invalid node identity: " <<
374 val[
"validation_public_key"].asString ();
382 if (val.isMember (
"manifest") && val[
"manifest"].isString ())
383 manifests.
push_back(val[
"manifest"].asString ());
389 publisherList.
begin (),
390 publisherList.
end ());
392 auto iNew = publisherList.
begin ();
393 auto iOld = oldList.
begin ();
394 while (iNew != publisherList.
end () ||
395 iOld != oldList.
end ())
397 if (iOld == oldList.
end () ||
398 (iNew != publisherList.
end () &&
405 else if (iNew == publisherList.
end () ||
406 (iOld != oldList.
end () && *iOld < *iNew))
422 if (publisherList.
empty())
425 "No validator keys included in valid list";
428 for (
auto const& valManifest : manifests)
435 "List for " <<
strHex(pubKey) <<
436 " contained untrusted validator manifest";
444 "List for " <<
strHex(pubKey) <<
445 " contained invalid validator manifest";
458 using namespace std::string_literals;
459 using namespace boost::filesystem;
460 using namespace boost::system::errc;
468 boost::system::error_code ec;
470 if (publisher.available)
473 boost::filesystem::path
const filename =
476 auto const fullPath{ canonical(filename, ec) };
480 auto size = file_size(fullPath, ec);
485 ec = make_error_code(no_such_file_or_directory);
491 #if _MSC_VER // MSVC: Windows paths need a leading / added
493 return fullPath.root_path() ==
"/"s ?
494 "file://" :
"file:///";
523 pubKey = m->masterKey;
524 auto const revoked = m->revoked();
538 auto const sig =
strUnHex(signature);
548 if (! r.
parse (data, list))
555 auto const sequence = list[
"sequence"].
asUInt();
591 boost::optional<PublicKey>
603 boost::optional<PublicKey>
636 "Removing validator list for publisher " <<
strHex(publisherKey);
638 for (
auto const& val : iList->second.list)
644 if (iVal->second <= 1)
650 iList->second.list.clear();
651 iList->second.available =
false;
663 boost::optional<TimeKeeper::time_point>
667 boost::optional<TimeKeeper::time_point> res{boost::none};
675 if (!res || p.second.expiration < *res)
676 res = p.second.expiration;
697 if (*when == TimeKeeper::time_point::max())
699 x[jss::expiration] =
"never";
700 x[jss::status] =
"active";
707 x[jss::status] =
"active";
709 x[jss::status] =
"expired";
714 x[jss::status] =
"unknown";
715 x[jss::expiration] =
"unknown";
726 for (
auto const& key : it->second.list)
739 curr[jss::pubkey_publisher] =
strHex(p.first);
740 curr[jss::available] = p.second.available;
741 curr[jss::uri] = p.second.siteUri;
744 curr[jss::seq] =
static_cast<Json::UInt>(p.second.sequence);
745 curr[jss::expiration] =
to_string(p.second.expiration);
749 for (
auto const& key : p.second.list)
787 func (v.first,
trusted(v.first));
796 uint256 const& hash)> func)
const
804 func(pl.rawManifest, pl.rawBlob, pl.rawSignature, pl.rawVersion,
805 key, pl.sequence, pl.hash);
809 boost::optional<Json::Value>
819 "Invalid requested validator list publisher key: " << pubKey;
828 || !iter->second.available)
833 value[
"manifest"] = iter->second.rawManifest;
834 value[
"blob"] = iter->second.rawBlob;
835 value[
"signature"] = iter->second.rawSignature;
836 value[
"version"] = iter->second.rawVersion;
849 if (! list.second.available)
892 <<
"Using unsafe quorum of "
894 <<
" as specified in the command line";
908 if (list.second.available &&
938 if (!trustChanges.
added.empty() || !trustChanges.
removed.empty())
948 <<
" listed validators eligible for inclusion in the trusted set";
953 <<
"Using quorum of " <<
quorum_ <<
" for new set of "
955 << trustChanges.
added.size() <<
" added, "
956 << trustChanges.
removed.size() <<
" removed)";
962 <<
" exceeds the number of trusted validators ("
boost::optional< PublicKey > getListedKey(PublicKey const &identity) const
Returns listed master public if public key is included on any lists.
ManifestCache & validatorManifests_
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)
void for_each_listed(std::function< void(PublicKey const &, bool)> func) const
Invokes the callback once for every listed validation public key.
bool addSuppressionPeer(uint256 const &key, PeerShortID peer)
PublicKey localPublicKey() const
Returns local validator public key.
PublicKey getMasterKey(PublicKey const &pk) const
Returns ephemeral signing key's master public key.
NodeID calcNodeID(PublicKey const &pk)
Calculate the 160-bit node ID from a node public key.
Stream trace() const
Severity stream access functions.
boost::optional< KeyType > publicKeyType(Slice const &slice)
Returns the type of public key.
Changes in trusted nodes after updating validator list.
@ stale
Trusted publisher key, but seq is too old.
An immutable linear range of bytes.
hash_map< PublicKey, PublisherList > publisherLists_
@ arrayValue
array value (ordered list)
boost::optional< Json::Value > getAvailable(boost::beast::string_view const &pubKey)
Returns the current valid list for the given publisher key, if available, as a Json object.
boost::filesystem::path GetCacheFileName(PublicKey const &pubKey)
Get the filename used for caching UNLs.
bool trustedPublisher(PublicKey const &identity) const
Returns true if public key is a trusted publisher.
virtual PeerSequence getActivePeers()=0
Returns a sequence representing the current list of peers.
Describes the result of processing a Validator List (UNL), including some of the information from the...
static const std::string filePrefix_
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
TrustChanges updateTrusted(hash_set< NodeID > const &seenValidators)
Update trusted nodes.
std::uint8_t const * data() const noexcept
Return a pointer to beginning of the storage.
ListDisposition verify(Json::Value &list, PublicKey &pubKey, std::string const &manifest, std::string const &blob, std::string const &signature)
Check response for trusted valid published list.
boost::optional< Blob > strUnHex(std::size_t strSize, Iterator begin, Iterator end)
std::string toStyledString() const
std::string to_string(ListDisposition disposition)
Unserialize a JSON document into a Value.
Routing table for objects identified by hash.
std::shared_timed_mutex mutex_
ValidatorList(ManifestCache &validatorManifests, ManifestCache &publisherManifests, TimeKeeper &timeKeeper, std::string const &databasePath, beast::Journal j, boost::optional< std::size_t > minimumQuorum=boost::none)
boost::optional< PublicKey > getTrustedKey(PublicKey const &identity) const
Returns master public key if public key is trusted.
bool verify(PublicKey const &publicKey, Slice const &m, Slice const &sig, bool mustBeFullyCanonical)
Verify a signature on a message.
void CacheValidatorFile(PublicKey const &pubKey, PublisherList const &publisher)
Write a JSON UNL to a cache file.
std::size_t calculateQuorum(std::size_t trusted, std::size_t seen)
Return quorum for trusted validator set.
Value & append(const Value &value)
Append value to array at the end.
const boost::filesystem::path dataPath_
@ objectValue
object value (collection of name/value pairs).
PublisherListStats applyList(std::string const &manifest, std::string const &blob, std::string const &signature, std::uint32_t version, std::string siteUri, boost::optional< uint256 > const &hash={})
Apply published list of public keys.
std::size_t size() const noexcept
hash_set< NodeID > removed
boost::optional< std::size_t > minimumQuorum_
ManifestCache & publisherManifests_
bool revoked(PublicKey const &pk) const
Returns true if master key has been revoked in a manifest.
bool listed(PublicKey const &identity) const
Returns true if public key is included on any lists.
void writeFileContents(boost::system::error_code &ec, boost::filesystem::path const &destPath, std::string const &contents)
std::string base64_decode(std::string const &data)
UInt size() const
Number of values in array or object.
void for_each_manifest(Function &&f) const
Invokes the callback once for every populated manifest.
@ untrusted
List signed by untrusted publisher key.
PublicKey getSigningKey(PublicKey const &pk) const
Returns master key's current signing key.
bool isMember(const char *key) const
Return true if the object has a member named key.
A generic endpoint for log messages.
static constexpr std::uint32_t requiredListVersion
PublisherListStats applyListAndBroadcast(std::string const &manifest, std::string const &blob, std::string const &signature, std::uint32_t version, std::string siteUri, uint256 const &hash, Overlay &overlay, HashRouter &hashRouter)
Apply published list of public keys, then broadcast it to all peers that have not seen it or sent it.
boost::optional< std::set< PeerShortID > > shouldRelay(uint256 const &key)
Determines whether the hashed item should be relayed.
T forward_as_tuple(T... args)
Manages various times used by the server.
@ unsupported_version
List version is not supported.
@ invalid
Timely, but invalid signature.
@ accepted
Manifest is valid.
Remembers manifests with the highest sequence number.
std::vector< std::string > loadLists()
T emplace_back(T... args)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
hash_set< PublicKey > trustedSigningKeys_
boost::optional< Manifest > deserializeManifest(Slice s)
Constructs Manifest from serialized string.
bool load(PublicKey const &localSigningKey, std::vector< std::string > const &configKeys, std::vector< std::string > const &publisherKeys)
Load configured trusted keys.
void for_each_available(std::function< void(std::string const &manifest, std::string const &blob, std::string const &signature, std::uint32_t version, PublicKey const &pubKey, std::size_t sequence, uint256 const &hash)> func) const
Invokes the callback once for every available publisher list's raw data members.
Manages the set of connected peers.
@ same_sequence
Same sequence as current list.
boost::optional< Blob > strViewUnHex(boost::string_view const &strSrc)
@ invalid
Invalid format or signature.
bool parse(std::string const &document, Value &root)
Read a Value from a JSON document.
virtual time_point now() const override=0
Returns the estimate of wall time, in network time.
Json::Value getJson() const
Return a JSON representation of the state of the validator list.
@ ValidatorListPropagation
std::string strHex(FwdIt begin, FwdIt end)
boost::optional< TimeKeeper::time_point > expires() const
Return the time when the validator list will expire.
bool trusted(PublicKey const &identity) const
Returns true if public key is trusted.
hash_set< PublicKey > trustedMasterKeys_
std::size_t count() const
Return the number of configured validator list sites.
ManifestDisposition applyManifest(Manifest m)
Add manifest to cache.
typename NetClock ::time_point time_point
hash_map< PublicKey, std::size_t > keyListings_
std::atomic< std::size_t > quorum_
typename NetClock ::duration duration
std::size_t quorum() const
Get quorum value for current trusted key set.
bool removePublisherList(PublicKey const &publisherKey)
Stop trusting publisher's list of keys.