Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Peer reservations #2935

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
2cd951e
Add empty peer reservation table
thejohnfreeman May 14, 2019
d46c241
Stub reservation RPC handlers
thejohnfreeman May 15, 2019
89b6a5b
Finish reservation command-line parsers
thejohnfreeman May 15, 2019
39e00ea
Take a stab at reservation RPC methods
thejohnfreeman May 15, 2019
f4edee3
Style fixes
thejohnfreeman May 15, 2019
33f4d4e
Add barebones Result monad
thejohnfreeman May 15, 2019
bb0c9e1
Fix Result and use it
thejohnfreeman May 15, 2019
b90fbe9
Remove Result; review fixes
thejohnfreeman May 22, 2019
4e369e1
Rename Ls -> List; take only base58 (no hex)
thejohnfreeman Jun 3, 2019
b286fa3
Read PeerReservations table during setup()
thejohnfreeman Jun 27, 2019
525f56a
Synchronize with SQLite table
thejohnfreeman Jun 27, 2019
8f864f0
Try to fix build
thejohnfreeman Jun 27, 2019
7300787
Manually convert ripple::PublicKey to std::string
thejohnfreeman Jun 27, 2019
7ce9f8d
Fix bugs
thejohnfreeman Jun 28, 2019
2a1df37
More bug fixes
thejohnfreeman Jun 29, 2019
a218aee
Preserve information
thejohnfreeman Jun 29, 2019
d063739
Fix bugs
thejohnfreeman Jul 1, 2019
3825a0c
FOLD: some review fixes
thejohnfreeman Jul 11, 2019
537fe44
FOLD: Use set instead of map
thejohnfreeman Jul 12, 2019
69018d3
FOLD: more review fixes
thejohnfreeman Aug 2, 2019
34973aa
FOLD: Remove last TODOs
thejohnfreeman Aug 2, 2019
a980f09
FOLD: do not abbreviate "peer reservation" in names
thejohnfreeman Aug 2, 2019
2bc748c
FOLD: fix code style
thejohnfreeman Aug 2, 2019
423baab
FOLD: Make PRT thread-safe
thejohnfreeman Aug 2, 2019
4c47c9c
FOLD: review fixes
thejohnfreeman Aug 5, 2019
c08cd11
FOLD: review fix
thejohnfreeman Aug 5, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2176,6 +2176,7 @@ else ()
src/ripple/overlay/impl/Message.cpp
src/ripple/overlay/impl/OverlayImpl.cpp
src/ripple/overlay/impl/PeerImp.cpp
src/ripple/overlay/impl/PeerReservationTable.cpp
src/ripple/overlay/impl/PeerSet.cpp
src/ripple/overlay/impl/TMHello.cpp
src/ripple/overlay/impl/TrafficCount.cpp
Expand Down Expand Up @@ -2242,6 +2243,7 @@ else ()
src/ripple/rpc/handlers/Ping.cpp
src/ripple/rpc/handlers/Print.cpp
src/ripple/rpc/handlers/Random.cpp
src/ripple/rpc/handlers/Reservations.cpp
src/ripple/rpc/handlers/RipplePathFind.cpp
src/ripple/rpc/handlers/ServerInfo.cpp
src/ripple/rpc/handlers/ServerState.cpp
Expand Down
15 changes: 15 additions & 0 deletions src/ripple/app/main/Application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
#include <ripple/json/json_reader.h>
#include <ripple/nodestore/DummyScheduler.h>
#include <ripple/overlay/Cluster.h>
#include <ripple/overlay/PeerReservationTable.h>
thejohnfreeman marked this conversation as resolved.
Show resolved Hide resolved
#include <ripple/overlay/make_Overlay.h>
#include <ripple/protocol/BuildInfo.h>
#include <ripple/protocol/Feature.h>
Expand Down Expand Up @@ -349,6 +350,7 @@ class ApplicationImp
TaggedCache <uint256, AcceptedLedger> m_acceptedLedgerCache;
std::unique_ptr <NetworkOPs> m_networkOPs;
std::unique_ptr <Cluster> cluster_;
std::unique_ptr <PeerReservationTable> peerReservations_;
std::unique_ptr <ManifestCache> validatorManifests_;
std::unique_ptr <ManifestCache> publisherManifests_;
std::unique_ptr <ValidatorList> validators_;
Expand Down Expand Up @@ -490,6 +492,8 @@ class ApplicationImp
, cluster_ (std::make_unique<Cluster> (
logs_->journal("Overlay")))

, peerReservations_(std::make_unique<PeerReservationTable>(logs_->journal("PeerReservationTable")))

, validatorManifests_ (std::make_unique<ManifestCache> (
logs_->journal("ManifestCache")))

Expand Down Expand Up @@ -765,6 +769,11 @@ class ApplicationImp
return *cluster_;
}

PeerReservationTable& peerReservations () override
{
return *peerReservations_;
}

SHAMapStore& getSHAMapStore () override
{
return *m_shaMapStore;
Expand Down Expand Up @@ -1197,6 +1206,12 @@ bool ApplicationImp::setup()
return false;
}

if (!peerReservations_->load(getWalletDB()))
{
JLOG(m_journal.fatal()) << "Cannot find peer reservations!";
return false;
}

if (validatorKeys_.publicKey.size())
setMaxDisallowedLedger();

Expand Down
2 changes: 2 additions & 0 deletions src/ripple/app/main/Application.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <ripple/core/Config.h>
#include <ripple/protocol/Protocol.h>
#include <ripple/beast/utility/PropertyStream.h>
#include <ripple/overlay/PeerReservationTable.h>
#include <boost/asio.hpp>
#include <memory>
#include <mutex>
Expand Down Expand Up @@ -139,6 +140,7 @@ class Application : public beast::PropertyStream::Source
virtual ManifestCache& validatorManifests () = 0;
virtual ManifestCache& publisherManifests () = 0;
virtual Cluster& cluster () = 0;
virtual PeerReservationTable& peerReservations () = 0;
virtual RCLValidations& getValidations () = 0;
virtual NodeStore::Database& getNodeStore () = 0;
virtual NodeStore::DatabaseShard* getShardStore() = 0;
Expand Down
6 changes: 6 additions & 0 deletions src/ripple/app/main/DBInit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,12 @@ const char* WalletDBInit[] =
PrivateKey CHARACTER(52) \
);",

// Peer reservations.
"CREATE TABLE IF NOT EXISTS PeerReservations ( \
PublicKey CHARACTER(53) UNIQUE NOT NULL, \
Description CHARACTER(64) NOT NULL \
);",

// Validator Manifests
"CREATE TABLE IF NOT EXISTS ValidatorManifests ( \
RawData BLOB NOT NULL \
Expand Down
3 changes: 3 additions & 0 deletions src/ripple/app/main/Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,9 @@ void printHelp (const po::options_description& desc)
" peers\n"
" ping\n"
" random\n"
" peer_reservations_add <public_key> [<description>]\n"
" peer_reservations_del <public_key>\n"
" peer_reservations_list\n"
" ripple ...\n"
" ripple_path_find <json> [<ledger>]\n"
" server_info [counters]\n"
Expand Down
3 changes: 2 additions & 1 deletion src/ripple/core/impl/DatabaseCon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ DatabaseCon::DatabaseCon (
}
catch (soci::soci_error&)
{
// ignore errors
// TODO: We should at least log this error. It is annoying to wire
// a logger into every context, but there are other solutions.
}
}
}
Expand Down
23 changes: 23 additions & 0 deletions src/ripple/net/impl/RPCCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -849,6 +849,26 @@ class RPCParser
return jvRequest;
}

// peer_reservations_add <public_key> [<name>]
Json::Value parsePeerReservationsAdd (Json::Value const& jvParams)
{
Json::Value jvRequest;
jvRequest[jss::public_key] = jvParams[0u].asString();
if (jvParams.size() > 1)
{
jvRequest[jss::description] = jvParams[1u].asString();
}
return jvRequest;
}

// peer_reservations_del <public_key>
Json::Value parsePeerReservationsDel (Json::Value const& jvParams)
{
Json::Value jvRequest;
jvRequest[jss::public_key] = jvParams[0u].asString();
return jvRequest;
}

// ripple_path_find <json> [<ledger>]
Json::Value parseRipplePathFind (Json::Value const& jvParams)
{
Expand Down Expand Up @@ -1127,6 +1147,9 @@ class RPCParser
{ "print", &RPCParser::parseAsIs, 0, 1 },
// { "profile", &RPCParser::parseProfile, 1, 9 },
{ "random", &RPCParser::parseAsIs, 0, 0 },
{ "peer_reservations_add", &RPCParser::parsePeerReservationsAdd, 1, 2 },
{ "peer_reservations_del", &RPCParser::parsePeerReservationsDel, 1, 1 },
{ "peer_reservations_list", &RPCParser::parseAsIs, 0, 0 },
{ "ripple_path_find", &RPCParser::parseRipplePathFind, 1, 2 },
{ "sign", &RPCParser::parseSignSubmit, 2, 3 },
{ "sign_for", &RPCParser::parseSignFor, 3, 4 },
Expand Down
123 changes: 123 additions & 0 deletions src/ripple/overlay/PeerReservationTable.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2019 Ripple Labs Inc.

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================

#ifndef RIPPLE_OVERLAY_PEER_RESERVATION_TABLE_H_INCLUDED
#define RIPPLE_OVERLAY_PEER_RESERVATION_TABLE_H_INCLUDED

#include <ripple/beast/hash/uhash.h>
#include <ripple/beast/hash/hash_append.h>
#include <ripple/beast/utility/Journal.h>
#include <ripple/json/json_forwards.h>
#include <ripple/protocol/PublicKey.h>

#define SOCI_USE_BOOST
#include <boost/optional.hpp>
#include <soci/soci.h>

#include <mutex>
#include <string>
#include <unordered_set>
#include <vector>

namespace ripple {

class DatabaseCon;

// Value type for reservations.
struct PeerReservation final
{
public:
PublicKey nodeId;
std::string description;

auto
toJson() const -> Json::Value;

template <typename Hasher>
friend void hash_append(Hasher& h, PeerReservation const& x) noexcept
{
using beast::hash_append;
hash_append(h, x.nodeId);
}

friend bool operator<(PeerReservation const& a, PeerReservation const& b)
{
return a.nodeId < b.nodeId;
}
};

// TODO: When C++20 arrives, take advantage of "equivalence" instead of
// "equality". Add an overload for `(PublicKey, PeerReservation)`, and just
// pass a `PublicKey` directly to `unordered_set.find`.
struct KeyEqual final
{
bool operator() (
PeerReservation const& lhs, PeerReservation const& rhs) const
{
return lhs.nodeId == rhs.nodeId;
}
};

class PeerReservationTable final
{
public:
explicit PeerReservationTable(
beast::Journal journal = beast::Journal(beast::Journal::getNullSink()))
: journal_(journal)
{
}

std::vector<PeerReservation> list() const;

bool
contains(PublicKey const& nodeId)
{
std::lock_guard<std::mutex> lock(this->mutex_);
return table_.find({nodeId}) != table_.end();
}

// Because `ApplicationImp` has two-phase initialization, so must we.
// Our dependencies are not prepared until the second phase.
bool
load(DatabaseCon& connection);

/**
* @return the replaced reservation if it existed
* @throw soci::soci_error
*/
auto
insert_or_assign(PeerReservation const& reservation)
-> boost::optional<PeerReservation>;
thejohnfreeman marked this conversation as resolved.
Show resolved Hide resolved

/**
* @return the erased reservation if it existed
*/
auto
erase(PublicKey const& nodeId) -> boost::optional<PeerReservation>;

private:
beast::Journal mutable journal_;
std::mutex mutable mutex_;
DatabaseCon* connection_;
std::unordered_set<PeerReservation, beast::uhash<>, KeyEqual> table_;
};

} // namespace ripple

#endif
29 changes: 18 additions & 11 deletions src/ripple/overlay/impl/OverlayImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -278,18 +278,25 @@ OverlayImpl::onHandoff (std::unique_ptr <beast::asio::ssl_bundle>&& ssl_bundle,
return handoff;
}

auto const result = m_peerFinder->activate (slot, *publicKey,
static_cast<bool>(app_.cluster().member(*publicKey)));
if (result != PeerFinder::Result::success)
{
m_peerFinder->on_closed(slot);
JLOG(journal.debug()) <<
"Peer " << remote_endpoint << " redirected, slots full";
handoff.moved = false;
handoff.response = makeRedirectResponse(slot, request,
remote_endpoint.address());
handoff.keep_alive = beast::rfc2616::is_keep_alive(request);
return handoff;
// The node gets a reserved slot if it is in our cluster
// or if it has a reservation.
bool const reserved {
static_cast<bool>(app_.cluster().member(*publicKey))
|| app_.peerReservations().contains(*publicKey)
};
auto const result = m_peerFinder->activate(slot, *publicKey, reserved);
if (result != PeerFinder::Result::success)
{
m_peerFinder->on_closed(slot);
JLOG(journal.debug())
<< "Peer " << remote_endpoint << " redirected, slots full";
handoff.moved = false;
handoff.response = makeRedirectResponse(
slot, request, remote_endpoint.address());
handoff.keep_alive = beast::rfc2616::is_keep_alive(request);
return handoff;
}
}

auto const peer = std::make_shared<PeerImp>(app_, id,
Expand Down
10 changes: 8 additions & 2 deletions src/ripple/overlay/impl/PeerImp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,12 @@ PeerImp::crawl() const
return boost::beast::detail::iequals(iter->value(), "public");
}

bool
PeerImp::cluster() const
{
return static_cast<bool>(app_.cluster().member(publicKey_));
}

std::string
PeerImp::getVersion() const
{
Expand Down Expand Up @@ -1614,7 +1620,7 @@ PeerImp::onMessage (std::shared_ptr <protocol::TMProposeSet> const& m)
{
protocol::TMProposeSet& set = *m;

if (set.has_hops() && ! slot_->cluster())
if (set.has_hops() && ! cluster())
set.set_hops(set.hops() + 1);

auto const sig = makeSlice(set.signature());
Expand Down Expand Up @@ -1983,7 +1989,7 @@ PeerImp::onMessage (std::shared_ptr <protocol::TMValidation> const& m)
{
auto const closeTime = app_.timeKeeper().closeTime();

if (m->has_hops() && ! slot_->cluster())
if (m->has_hops() && ! cluster())
m->set_hops(m->hops() + 1);

if (m->validation ().size () < 50)
Expand Down
5 changes: 1 addition & 4 deletions src/ripple/overlay/impl/PeerImp.h
Original file line number Diff line number Diff line change
Expand Up @@ -281,10 +281,7 @@ class PeerImp
crawl() const;

bool
cluster() const override
{
return slot_->cluster();
}
cluster() const override;

void
check();
Expand Down