From 9316f2458cb599cec6323aac087f5f7c91c697f7 Mon Sep 17 00:00:00 2001 From: Edward Hennis Date: Thu, 21 Jan 2021 18:39:14 -0500 Subject: [PATCH] [WIP] Toying with the idea of VL exchange * Log Validator Lists received from peers --- src/xrpld/app/misc/ValidatorList.h | 16 ++++- src/xrpld/app/misc/detail/ValidatorList.cpp | 69 +++++++++++++++++-- src/xrpld/overlay/detail/PeerImp.cpp | 76 ++++++++++++++++++++- 3 files changed, 152 insertions(+), 9 deletions(-) diff --git a/src/xrpld/app/misc/ValidatorList.h b/src/xrpld/app/misc/ValidatorList.h index 77793619ac9..c3945430931 100644 --- a/src/xrpld/app/misc/ValidatorList.h +++ b/src/xrpld/app/misc/ValidatorList.h @@ -344,7 +344,7 @@ class ValidatorList static std::vector parseBlobs(protocol::TMValidatorListCollection const& body); - static void + static std::optional sendValidatorList( Peer& peer, std::uint64_t peerSequence, @@ -356,6 +356,18 @@ class ValidatorList HashRouter& hashRouter, beast::Journal j); + std::tuple< + std::string, + std::uint32_t, + std::map, + uint256> + sendLatestValidatorLists( + Peer& peer, + std::uint64_t peerSequence, + PublicKey const& publisherKey, + HashRouter& hashRouter, + beast::Journal j) const; + [[nodiscard]] static std::pair buildValidatorListMessages( std::size_t messageVersion, @@ -796,7 +808,7 @@ class ValidatorList HashRouter& hashRouter, beast::Journal j); - static void + static std::optional sendValidatorList( Peer& peer, std::uint64_t peerSequence, diff --git a/src/xrpld/app/misc/detail/ValidatorList.cpp b/src/xrpld/app/misc/detail/ValidatorList.cpp index 566dfc06a07..5d231c28b26 100644 --- a/src/xrpld/app/misc/detail/ValidatorList.cpp +++ b/src/xrpld/app/misc/detail/ValidatorList.cpp @@ -716,8 +716,62 @@ ValidatorList::buildValidatorListMessages( return {0, 0}; } +std::tuple< + std::string, + std::uint32_t, + std::map, + uint256> +ValidatorList::sendLatestValidatorLists( + Peer& peer, + std::uint64_t peerSequence, + PublicKey const& publisherKey, + HashRouter& hashRouter, + beast::Journal j) const +{ + std::vector messages; + std::map blobInfos; + + if (publisherLists_.count(publisherKey) == 0) + return {}; + ValidatorList::PublisherListCollection const& lists = + publisherLists_.at(publisherKey); + + auto const maxSequence = lists.current.sequence; + ASSERT( + lists.current.sequence == maxSequence || + lists.remaining.count(maxSequence) == 1, + "ripple::ValidatorList::sendLatestValidatorLists : valid sequence"); + + if (peerSequence < maxSequence) + { + buildBlobInfos(blobInfos, lists); + sendValidatorList( + peer, + peerSequence, + publisherKey, + maxSequence, + lists.rawVersion, + lists.rawManifest, + blobInfos, + messages, + hashRouter, + j); + + // Suppress the messages so they'll be ignored next time. + uint256 lasthash; + for (auto const& m : messages) + { + lasthash = m.hash; + hashRouter.addSuppressionPeer(lasthash, peer.id()); + } + return std::make_tuple( + lists.rawManifest, lists.rawVersion, blobInfos, lasthash); + } + return {}; +} + // static -void +std::optional ValidatorList::sendValidatorList( Peer& peer, std::uint64_t peerSequence, @@ -735,7 +789,7 @@ ValidatorList::sendValidatorList( : peer.supportsFeature(ProtocolFeature::ValidatorListPropagation) ? 1 : 0; if (!messageVersion) - return; + return {}; auto const [newPeerSequence, numVLs] = buildValidatorListMessages( messageVersion, peerSequence, @@ -771,12 +825,15 @@ ValidatorList::sendValidatorList( if (sent) { if (messageVersion > 1) + { JLOG(j.debug()) << "Sent " << messages.size() << " validator list collection(s) containing " << numVLs << " validator list(s) for " << strHex(publisherKey) << " with sequence range " << peerSequence << ", " << newPeerSequence << " to " << peer.fingerprint(); + return "ValidatorListCollection"; + } else { XRPL_ASSERT( @@ -787,13 +844,15 @@ ValidatorList::sendValidatorList( << "Sent validator list for " << strHex(publisherKey) << " with sequence " << newPeerSequence << " to " << peer.fingerprint(); + return "ValidatorList"; } } } + return {}; } // static -void +std::optional ValidatorList::sendValidatorList( Peer& peer, std::uint64_t peerSequence, @@ -806,7 +865,7 @@ ValidatorList::sendValidatorList( beast::Journal j) { std::vector messages; - sendValidatorList( + return sendValidatorList( peer, peerSequence, publisherKey, @@ -877,7 +936,7 @@ ValidatorList::broadcastBlobs( std::map blobInfos; XRPL_ASSERT( - lists.current.sequence == maxSequence || + lists.current.sequence <= maxSequence || lists.remaining.count(maxSequence) == 1, "ripple::ValidatorList::broadcastBlobs : valid sequence"); // Can't use overlay.foreach here because we need to modify diff --git a/src/xrpld/overlay/detail/PeerImp.cpp b/src/xrpld/overlay/detail/PeerImp.cpp index b85536c6f1b..3724d807553 100644 --- a/src/xrpld/overlay/detail/PeerImp.cpp +++ b/src/xrpld/overlay/detail/PeerImp.cpp @@ -886,6 +886,46 @@ PeerImp::domain() const // Protocol logic +void +logVLBlob(beast::Journal j, ValidatorBlobInfo const& blob, std::size_t count) +{ + auto const stream = j.trace(); + JLOG(stream) << "Blob " << count << " Signature: " << blob.signature; + JLOG(stream) << "Blob " << count << " blob: " << base64_decode(blob.blob); + JLOG(stream) << "Blob " << count << " manifest: " + << (blob.manifest ? base64_decode(*blob.manifest) : "NONE"); +} + +void +logVLBlob( + beast::Journal j, + std::pair const& blob, + std::size_t count) +{ + logVLBlob(j, blob.second, count); +} + +template +void +logVL( + beast::Journal j, + std::string const& manifest, + std::uint32_t version, + TBlobs const& blobs, + uint256 const& hash) +{ + auto const stream = j.trace(); + JLOG(stream) << "Manifest: " << manifest; + JLOG(stream) << "Version: " << version; + JLOG(stream) << "Hash: " << hash; + std::size_t count = 1; + for (auto const& blob : blobs) + { + logVLBlob(j, blob, count); + ++count; + } +} + void PeerImp::doProtocolStart() { @@ -2142,6 +2182,8 @@ PeerImp::onValidatorListMessage( return; } + logVL(p_journal_, manifest, version, blobs, hash); + auto const applyResult = app_.validators().applyListsAndBroadcast( manifest, version, @@ -2183,7 +2225,8 @@ PeerImp::onValidatorListMessage( "ripple::PeerImp::onValidatorListMessage : lower sequence"); } #endif - publisherListSequences_[pubKey] = applyResult.sequence; + if (publisherListSequences_[pubKey] < applyResult.sequence) + publisherListSequences_[pubKey] = applyResult.sequence; } break; case ListDisposition::same_sequence: @@ -2202,8 +2245,37 @@ PeerImp::onValidatorListMessage( } #endif // !NDEBUG + [[fallthrough]]; + case ListDisposition::stale: { + auto const [pubKey, currentPeerSeq] = [&]() { + std::lock_guard sl(recentLock_); + ASSERT( + applyResult.sequence && applyResult.publisherKey, + "ripple::PeerImp::onValidatorListMessage : (stale) nonzero " + "sequence"); + auto const& pubKey = *applyResult.publisherKey; + auto const& current = publisherListSequences_[pubKey]; + ASSERT( + current <= applyResult.sequence, + "ripple::PeerImp::onValidatorListMessage : (stale) valid " + "sequence"); + return std::make_pair( + pubKey, current ? current : applyResult.sequence); + }(); + if (currentPeerSeq <= applyResult.sequence) + { + auto const [sentmanifest, sentversion, sentblobs, senthash] = + app_.validators().sendLatestValidatorLists( + *this, + currentPeerSeq, + pubKey, + app_.getHashRouter(), + p_journal_); + logVL( + p_journal_, sentmanifest, sentversion, sentblobs, senthash); + } + } break; - case ListDisposition::stale: case ListDisposition::untrusted: case ListDisposition::invalid: case ListDisposition::unsupported_version: