diff --git a/src/ripple/app/misc/ValidatorList.h b/src/ripple/app/misc/ValidatorList.h index 01c672e4f9b..eb878a94748 100644 --- a/src/ripple/app/misc/ValidatorList.h +++ b/src/ripple/app/misc/ValidatorList.h @@ -197,9 +197,9 @@ class ValidatorList } ListDisposition disposition; - PublicKey publisherKey; + boost::optional publisherKey; bool available = false; - std::size_t sequence; + boost::optional sequence; }; /** Load configured trusted keys. @@ -514,6 +514,17 @@ class ValidatorList private: + /** Get the filename used for caching UNLs + */ + boost::filesystem::path + GetCacheFileName(PublicKey const& pubKey); + + /** Write a JSON UNL to a cache file + */ + void + CacheValidatorFile(PublicKey const& pubKey, + PublisherList const& publisher); + /** Check response for trusted valid published list @return `ListDisposition::accepted` if list can be applied diff --git a/src/ripple/app/misc/impl/ValidatorList.cpp b/src/ripple/app/misc/impl/ValidatorList.cpp index 32e7cc93cdb..ef0b2762c37 100644 --- a/src/ripple/app/misc/impl/ValidatorList.cpp +++ b/src/ripple/app/misc/impl/ValidatorList.cpp @@ -199,6 +199,46 @@ ValidatorList::load ( return true; } +boost::filesystem::path +ValidatorList::GetCacheFileName(PublicKey const& pubKey) +{ + return dataPath_ / (filePrefix_ + strHex(pubKey)); +} + +void +ValidatorList::CacheValidatorFile(PublicKey const& pubKey, + PublisherList const& publisher) +{ + if (!dataPath_.empty()) + { + boost::filesystem::path const filename = + GetCacheFileName(pubKey); + + boost::system::error_code ec; + + Json::Value value(Json::objectValue); + + value["manifest"] = publisher.rawManifest; + value["blob"] = publisher.rawBlob; + value["signature"] = publisher.rawSignature; + value["version"] = publisher.rawVersion; + + writeFileContents(ec, filename, value.toStyledString()); + + if (ec) + { + // Log and ignore any file I/O exceptions + JLOG(j_.error()) << + "Problem writing " << + filename << + " " << + ec.value() << + ": " << + ec.message(); + } + } +} + ValidatorList::PublisherListStats ValidatorList::applyListAndBroadcast( std::string const& manifest, @@ -211,7 +251,7 @@ ValidatorList::applyListAndBroadcast( HashRouter& hashRouter) { auto const result = applyList(manifest, blob, signature, - version, siteUri, hash); + version, std::move(siteUri), hash); auto const disposition = result.disposition; bool broadcast = disposition == ListDisposition::accepted || @@ -219,7 +259,7 @@ ValidatorList::applyListAndBroadcast( if (broadcast) { - assert(result.available); + assert(result.available && result.publisherKey && result.sequence); protocol::TMValidatorList msg; msg.set_manifest(manifest); msg.set_blob(blob); @@ -230,8 +270,8 @@ ValidatorList::applyListAndBroadcast( if (toSkip) { - auto const& publisherKey = result.publisherKey; - auto const sequence = result.sequence; + auto const& publisherKey = *result.publisherKey; + auto const sequence = *result.sequence; auto peercondition = [&publisherKey, &sequence] @@ -410,41 +450,7 @@ ValidatorList::applyList ( } // Cache the validator list in a file - if (!dataPath_.empty()) - { - boost::filesystem::path const filename{ - dataPath_ / (filePrefix_ + strHex(pubKey)) }; - try - { - boost::system::error_code ec; - - Json::Value value(Json::objectValue); - - value["manifest"] = publisher.rawManifest; - value["blob"] = publisher.rawBlob; - value["signature"] = publisher.rawSignature; - value["version"] = publisher.rawVersion; - - writeFileContents(ec, filename, value.toStyledString()); - if (ec) - { - // Log and ignore any file I/O exceptions - JLOG(j_.error()) << - "Problem writing " << - filename << - " " << - ec.value() << - ": " << - ec.message(); - } - } - catch (std::exception const& e) - { - // Log and ignore any file I/O exceptions - JLOG(j_.error()) << "Exception writing validator list to file " << - filename << ": " << e.what(); - } - } + CacheValidatorFile(pubKey, publisher); return applyResult; } @@ -467,38 +473,37 @@ ValidatorList::loadLists() if (publisher.available) continue; - boost::filesystem::path const filename{ - dataPath_ / (filePrefix_ + strHex(pubKey)) }; + boost::filesystem::path const filename = + GetCacheFileName(pubKey); auto const fullPath{ canonical(filename, ec) }; - if (!ec) + if (ec) + continue; + + auto size = file_size(fullPath, ec); + if (!ec && !size) { - auto size = file_size(fullPath, ec); - if (!ec && !size) - { - // Treat an empty file as a missing file, because - // nobody else is going to write it. - ec = make_error_code(no_such_file_or_directory); - } + // Treat an empty file as a missing file, because + // nobody else is going to write it. + ec = make_error_code(no_such_file_or_directory); } + if (ec) + continue; - if (!ec) - { - std::string const prefix = [&fullPath]() { + std::string const prefix = [&fullPath]() { #if _MSC_VER // MSVC: Windows paths need a leading / added - { - return fullPath.root_path() == "/"s ? - "file://" : "file:///"; - } + { + return fullPath.root_path() == "/"s ? + "file://" : "file:///"; + } #else - { - (void)fullPath; - return "file://"; - } + { + (void)fullPath; + return "file://"; + } #endif - }(); - sites.emplace_back(prefix + fullPath.string()); - } + }(); + sites.emplace_back(prefix + fullPath.string()); } // Then let the ValidatorSites do the rest of the work. diff --git a/src/ripple/overlay/impl/PeerImp.cpp b/src/ripple/overlay/impl/PeerImp.cpp index 8f7e40b6154..33f8cce4839 100644 --- a/src/ripple/overlay/impl/PeerImp.cpp +++ b/src/ripple/overlay/impl/PeerImp.cpp @@ -2048,7 +2048,8 @@ PeerImp::onMessage (std::shared_ptr const& m) auto const disp = applyResult.disposition; JLOG(p_journal_.debug()) << "Processed validator list from " << - strHex(applyResult.publisherKey) << " from " << + (applyResult.publisherKey ? strHex(*applyResult.publisherKey) : + "unknown or invalid publisher") << " from " << remote_address_.to_string() << " (" << id_ << ") with result " << to_string(disp); @@ -2065,10 +2066,11 @@ PeerImp::onMessage (std::shared_ptr const& m) std::lock_guard sl(recentLock_); - auto const& pubKey = applyResult.publisherKey; + assert(applyResult.sequence && applyResult.publisherKey); + auto const& pubKey = *applyResult.publisherKey; assert(publisherListSequences_.count(pubKey) == 0 || - publisherListSequences_[pubKey] < applyResult.sequence); - publisherListSequences_[pubKey] = applyResult.sequence; + publisherListSequences_[pubKey] < *applyResult.sequence); + publisherListSequences_[pubKey] = *applyResult.sequence; } break; @@ -2083,8 +2085,9 @@ PeerImp::onMessage (std::shared_ptr const& m) #ifndef NDEBUG { std::lock_guard sl(recentLock_); - assert(publisherListSequences_[applyResult.publisherKey] - == applyResult.sequence); + assert(applyResult.sequence && applyResult.publisherKey); + assert(publisherListSequences_[*applyResult.publisherKey] + == *applyResult.sequence); } #endif // !NDEBUG