mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-19 18:45:52 +00:00
Compare commits
19 Commits
0.29.1-rc1
...
0.30.0-hf1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aa4f347e7c | ||
|
|
0a0adaac6d | ||
|
|
3d2aae9ea5 | ||
|
|
3d5ff2b4cd | ||
|
|
d20f0d5014 | ||
|
|
a8859b495b | ||
|
|
caccee1d98 | ||
|
|
379110a8a2 | ||
|
|
8d37cd9169 | ||
|
|
b40ade5165 | ||
|
|
c475b23c7d | ||
|
|
d6b9cfcc34 | ||
|
|
0c05bd3def | ||
|
|
8f7ab21423 | ||
|
|
07418cfb34 | ||
|
|
ac9816c01d | ||
|
|
bd3e4ac11c | ||
|
|
926d08db6f | ||
|
|
a23f6457dc |
@@ -1,14 +1,18 @@
|
||||
%define rippled_branch %(echo $RIPPLED_BRANCH)
|
||||
Name: rippled
|
||||
Version: 0.29.1-rc1
|
||||
Release: 1%{?dist}
|
||||
# Version must be limited to MAJOR.MINOR.PATCH
|
||||
Version: 0.30.0
|
||||
# Release should include either the build or hotfix number (ex: hf1%{?dist} or b2%{?dist})
|
||||
# If there is no b# or hf#, then use 1%{?dist}
|
||||
Release: %{?dist}
|
||||
Summary: Ripple peer-to-peer network daemon
|
||||
|
||||
Group: Applications/Internet
|
||||
License: ISC
|
||||
URL: https://github.com/ripple/rippled
|
||||
|
||||
# curl -L -o SOURCES/rippled-release.zip https://github.com/ripple/rippled/archive/release.zip
|
||||
Source0: rippled-release.zip
|
||||
# curl -L -o SOURCES/rippled-release.zip https://github.com/ripple/rippled/archive/${RIPPLED_BRANCH}.zip
|
||||
Source0: rippled-%{rippled_branch}.zip
|
||||
BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
|
||||
|
||||
BuildRequires: gcc-c++ scons openssl-devel protobuf-devel
|
||||
@@ -20,13 +24,11 @@ Rippled is the server component of the Ripple network.
|
||||
|
||||
|
||||
%prep
|
||||
%setup -n rippled-release
|
||||
%setup -n rippled-%{rippled_branch}
|
||||
|
||||
|
||||
%build
|
||||
# Assume boost is manually installed
|
||||
export RIPPLED_BOOST_HOME=/usr/local/boost_1_55_0
|
||||
scons -j `grep -c processor /proc/cpuinfo` build/rippled
|
||||
scons -j `grep -c processor /proc/cpuinfo`
|
||||
|
||||
|
||||
%install
|
||||
@@ -49,4 +51,4 @@ rm -rf %{buildroot}
|
||||
%defattr(-,root,root,-)
|
||||
/usr/bin/rippled
|
||||
/usr/share/rippled/LICENSE
|
||||
/etc/rippled/rippled-example.cfg
|
||||
%config(noreplace) /etc/rippled/rippled.cfg
|
||||
|
||||
@@ -359,38 +359,18 @@
|
||||
#
|
||||
#
|
||||
#
|
||||
# [overlay] EXPERIMENTAL
|
||||
# [overlay]
|
||||
#
|
||||
# This section is EXPERIMENTAL, and should not be
|
||||
# present for production configuration settings.
|
||||
# Controls settings related to the peer to peer overlay.
|
||||
#
|
||||
# A set of key/value pair parameters to configure the overlay.
|
||||
#
|
||||
# auto_connect = 0 | 1
|
||||
#
|
||||
# When set, activates the autoconnect feature. This maintains outgoing
|
||||
# connections using PeerFinder's "Outgoing Connection Strategy."
|
||||
#
|
||||
# become_superpeer = 'never' | 'always' | 'auto'
|
||||
#
|
||||
# Controls the selection of peer roles:
|
||||
#
|
||||
# 'never' Always handshake in the leaf role.
|
||||
# 'always' Always handshake in the superpeer role.
|
||||
# 'auto' Start as a leaf, promote to superpeer after
|
||||
# passing capability check (default).
|
||||
#
|
||||
# In the leaf role, a peer does not advertise its IP and port for
|
||||
# the purpose of receiving incoming connections. The peer also does
|
||||
# not forward transactions and validations received from other peers.
|
||||
#
|
||||
# In the superpeer role, a peer advertises its IP and port for
|
||||
# receiving incoming connections after passing an incoming connection
|
||||
# test. Superpeers forward transactions and protocol messages to all
|
||||
# other peers. Superpeers do not forward validations to other superpeers.
|
||||
# Instead, a validation received by a superpeer from a leaf is forwarded
|
||||
# only to other leaf connections.
|
||||
# public_ip = <IP-address>
|
||||
#
|
||||
# If the server has a known, fixed public IPv4 address,
|
||||
# specify that IP address here in dotted decimal notation.
|
||||
# Peers will use this information to reject attempt to proxy
|
||||
# connections to or from this server.
|
||||
#
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
@@ -147,8 +147,7 @@ bool is_public (AddressV4 const& addr)
|
||||
{
|
||||
return
|
||||
! is_private (addr) &&
|
||||
! is_multicast (addr) &&
|
||||
(addr != AddressV4::broadcast (addr));
|
||||
! is_multicast (addr);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@@ -298,6 +298,13 @@ LedgerConsensusImp::LedgerConsensusImp (
|
||||
// update the network status table as to whether we're
|
||||
// proposing/validating
|
||||
consensus_.setProposing (mProposing, mValidating);
|
||||
|
||||
playbackProposals ();
|
||||
if (mPeerPositions.size () > (mPreviousProposers / 2))
|
||||
{
|
||||
// We may be falling behind, don't wait for the timer
|
||||
timerEntry ();
|
||||
}
|
||||
}
|
||||
|
||||
Json::Value LedgerConsensusImp::getJson (bool full)
|
||||
@@ -479,9 +486,15 @@ void LedgerConsensusImp::mapCompleteInternal (
|
||||
else
|
||||
assert (false); // We don't have our own position?!
|
||||
}
|
||||
else
|
||||
else if (!mOurPosition)
|
||||
JLOG (j_.debug)
|
||||
<< "Not creating disputes: no position yet.";
|
||||
else if (mOurPosition->isBowOut ())
|
||||
JLOG (j_.warning)
|
||||
<< "Not ready to create disputes";
|
||||
<< "Not creating disputes: not participating.";
|
||||
else
|
||||
JLOG (j_.debug)
|
||||
<< "Not creating disputes: identical position.";
|
||||
|
||||
mAcquired[hash] = map;
|
||||
|
||||
@@ -970,8 +983,6 @@ void LedgerConsensusImp::accept (std::shared_ptr<SHAMap> set)
|
||||
consensus_.takePosition (mPreviousLedger->info().seq, set);
|
||||
|
||||
assert (set->getHash () == mOurPosition->getCurrentHash ());
|
||||
// these are now obsolete
|
||||
consensus_.peekStoredProposals ().clear ();
|
||||
}
|
||||
|
||||
auto closeTime = mOurPosition->getCloseTime();
|
||||
@@ -993,8 +1004,8 @@ void LedgerConsensusImp::accept (std::shared_ptr<SHAMap> set)
|
||||
// If we don't have a close time, then we just agree to disagree
|
||||
bool const closeTimeCorrect = (closeTime != 0);
|
||||
|
||||
// Switch to new semantics on Sep 30, 2015 at 11:00:00am PDT
|
||||
if (mPreviousLedger->info().closeTime > 497296800)
|
||||
// Switch to new semantics on Oct 27, 2015 at 11:00:00am PDT
|
||||
if (mPreviousLedger->info().closeTime > 499284000)
|
||||
{
|
||||
// Ledger close times should increase strictly monotonically
|
||||
if (closeTime <= mPreviousLedger->info().closeTime)
|
||||
@@ -1017,7 +1028,7 @@ void LedgerConsensusImp::accept (std::shared_ptr<SHAMap> set)
|
||||
<< "Report: TxSt = " << set->getHash ()
|
||||
<< ", close " << closeTime << (closeTimeCorrect ? "" : "X");
|
||||
|
||||
// Put failed transactions into a deterministic order
|
||||
// Put transactions into a deterministic, but unpredictable, order
|
||||
CanonicalTXSet retriableTxs (set->getHash ());
|
||||
|
||||
// Build the new last closed ledger
|
||||
@@ -1540,8 +1551,10 @@ void LedgerConsensusImp::updateOurPositions ()
|
||||
else
|
||||
{
|
||||
// proposal is still fresh
|
||||
++closeTimes[roundCloseTime (
|
||||
it->second->getCloseTime (), mCloseResolution)];
|
||||
++closeTimes[std::max (
|
||||
roundCloseTime (it->second->getCloseTime (),
|
||||
mCloseResolution),
|
||||
mPreviousLedger->info().closeTime + 1)];
|
||||
++it;
|
||||
}
|
||||
}
|
||||
@@ -1593,16 +1606,20 @@ void LedgerConsensusImp::updateOurPositions ()
|
||||
{
|
||||
// no other times
|
||||
mHaveCloseTimeConsensus = true;
|
||||
closeTime = roundCloseTime (
|
||||
mOurPosition->getCloseTime (), mCloseResolution);
|
||||
closeTime = std::max(
|
||||
roundCloseTime (mOurPosition->getCloseTime (),
|
||||
mCloseResolution),
|
||||
mPreviousLedger->info().closeTime + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
int participants = mPeerPositions.size ();
|
||||
if (mProposing)
|
||||
{
|
||||
++closeTimes[roundCloseTime (
|
||||
mOurPosition->getCloseTime (), mCloseResolution)];
|
||||
++closeTimes[std::max (
|
||||
roundCloseTime (mOurPosition->getCloseTime (),
|
||||
mCloseResolution),
|
||||
mPreviousLedger->info().closeTime + 1)];
|
||||
++participants;
|
||||
}
|
||||
|
||||
@@ -1652,8 +1669,7 @@ void LedgerConsensusImp::updateOurPositions ()
|
||||
}
|
||||
|
||||
if (!changes &&
|
||||
((closeTime != roundCloseTime (
|
||||
mOurPosition->getCloseTime (), mCloseResolution))
|
||||
((closeTime != mOurPosition->getCloseTime ())
|
||||
|| mOurPosition->isStale (ourCutoff)))
|
||||
{
|
||||
// close time changed or our position is stale
|
||||
@@ -1866,6 +1882,11 @@ void applyTransactions (
|
||||
CanonicalTXSet& retriableTxs,
|
||||
ApplyFlags flags)
|
||||
{
|
||||
|
||||
// Switch to new transaction ordering on
|
||||
// October 27, 2015 at 11:00AM PDT
|
||||
bool const newTxOrder = checkLedger->info().closeTime > 499284000;
|
||||
|
||||
auto j = app.journal ("LedgerConsensus");
|
||||
if (set)
|
||||
{
|
||||
@@ -1889,11 +1910,15 @@ void applyTransactions (
|
||||
|
||||
if (txn)
|
||||
{
|
||||
if (applyTransaction(app, view, txn, true, flags, j) ==
|
||||
if (newTxOrder)
|
||||
{
|
||||
// All transactions execute in canonical order
|
||||
retriableTxs.insert (txn);
|
||||
}
|
||||
else if (applyTransaction(app, view, txn, true, flags, j) ==
|
||||
LedgerConsensusImp::resultRetry)
|
||||
{
|
||||
// On failure, stash the failed transaction for
|
||||
// later retry.
|
||||
// Failures are retried in canonical order
|
||||
retriableTxs.insert (txn);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -972,6 +972,8 @@ public:
|
||||
<< "Consensus triggered check of ledger";
|
||||
checkAccept (maxLedger, maxSeq);
|
||||
}
|
||||
|
||||
mLedgerHistory.builtLedger (ledger);
|
||||
}
|
||||
|
||||
void advanceThread()
|
||||
|
||||
@@ -282,7 +282,7 @@ int run (int argc, char** argv)
|
||||
("conf", po::value<std::string> (), "Specify the configuration file.")
|
||||
("rpc", "Perform rpc command (default).")
|
||||
("rpc_ip", po::value <std::string> (), "Specify the IP address for RPC command. Format: <ip-address>[':'<port-number>]")
|
||||
("rpc_port", po::value <int> (), "Specify the port number for RPC command.")
|
||||
("rpc_port", po::value <std::uint16_t> (), "Specify the port number for RPC command.")
|
||||
("standalone,a", "Run with no peers.")
|
||||
("shutdowntest", po::value <std::string> ()->implicit_value (""), "Perform shutdown tests.")
|
||||
("unittest,u", po::value <std::string> ()->implicit_value (""), "Perform unit tests.")
|
||||
@@ -438,9 +438,9 @@ int run (int argc, char** argv)
|
||||
{
|
||||
try
|
||||
{
|
||||
config->rpc_ip =
|
||||
config->rpc_ip.emplace (
|
||||
boost::asio::ip::address_v4::from_string(
|
||||
vm["rpc_ip"].as<std::string>());
|
||||
vm["rpc_ip"].as<std::string>()));
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
@@ -456,7 +456,8 @@ int run (int argc, char** argv)
|
||||
{
|
||||
try
|
||||
{
|
||||
config->rpc_port = vm["rpc_port"].as<std::uint16_t>();
|
||||
config->rpc_port.emplace (
|
||||
vm["rpc_port"].as<std::uint16_t>());
|
||||
|
||||
if (*config->rpc_port == 0)
|
||||
throw std::domain_error ("");
|
||||
|
||||
@@ -76,17 +76,17 @@ public:
|
||||
using const_iterator = std::map <Key, std::shared_ptr<STTx const>>::const_iterator;
|
||||
|
||||
public:
|
||||
explicit CanonicalTXSet (LedgerHash const& lastClosedLedgerHash)
|
||||
: mSetHash (lastClosedLedgerHash)
|
||||
explicit CanonicalTXSet (LedgerHash const& saltHash)
|
||||
: mSetHash (saltHash)
|
||||
{
|
||||
}
|
||||
|
||||
void insert (std::shared_ptr<STTx const> const& txn);
|
||||
|
||||
// VFALCO TODO remove this function
|
||||
void reset (LedgerHash const& newLastClosedLedgerHash)
|
||||
void reset (LedgerHash const& saltHash)
|
||||
{
|
||||
mSetHash = newLastClosedLedgerHash;
|
||||
mSetHash = saltHash;
|
||||
|
||||
mMap.clear ();
|
||||
}
|
||||
|
||||
@@ -1384,6 +1384,9 @@ void NetworkOPsImp::processTrustedProposal (
|
||||
|
||||
bool relay = true;
|
||||
|
||||
if (mConsensus)
|
||||
mConsensus->storeProposal (proposal, nodePublic);
|
||||
|
||||
if (!haveConsensusObject ())
|
||||
{
|
||||
m_journal.info << "Received proposal outside consensus window";
|
||||
@@ -1393,8 +1396,6 @@ void NetworkOPsImp::processTrustedProposal (
|
||||
}
|
||||
else
|
||||
{
|
||||
mConsensus->storeProposal (proposal, nodePublic);
|
||||
|
||||
if (mLedgerConsensus->getLCL () == proposal->getPrevLedger ())
|
||||
{
|
||||
relay = mLedgerConsensus->peerPosition (proposal);
|
||||
|
||||
@@ -242,6 +242,7 @@ Json::Value PathRequest::doCreate (
|
||||
if (parseJson (value) != PFR_PJ_INVALID)
|
||||
{
|
||||
valid = isValid (cache);
|
||||
if (! hasCompletion())
|
||||
status = valid ? doUpdate(cache, true) : jvStatus;
|
||||
}
|
||||
else
|
||||
|
||||
@@ -270,8 +270,6 @@ void Config::setup (std::string const& strConf, bool bQuiet)
|
||||
}
|
||||
}
|
||||
|
||||
HTTPClient::initializeSSLContext(*this);
|
||||
|
||||
// Update default values
|
||||
load ();
|
||||
{
|
||||
@@ -290,6 +288,8 @@ void Config::setup (std::string const& strConf, bool bQuiet)
|
||||
boost::str (boost::format ("Can not create %s") % dataDir));
|
||||
|
||||
legacy ("database_path", boost::filesystem::absolute (dataDir).string ());
|
||||
|
||||
HTTPClient::initializeSSLContext(*this);
|
||||
}
|
||||
|
||||
void Config::load ()
|
||||
|
||||
@@ -98,7 +98,7 @@ public:
|
||||
: m_skip (0)
|
||||
{
|
||||
// The format is: <02> <length of signature> <signature>
|
||||
if ((sig[0] != 0x02) || (size < 3))
|
||||
if ((size < 3) || (sig[0] != 0x02))
|
||||
return;
|
||||
|
||||
std::size_t const len (sig[1]);
|
||||
|
||||
@@ -271,12 +271,13 @@ unsigned long RFC1751::extract (char const* s, int start, int length)
|
||||
assert (length >= 0);
|
||||
assert (start + length <= 66);
|
||||
|
||||
int const shiftR = 24 - (length + (start % 8));
|
||||
cl = s[start / 8]; // get components
|
||||
cc = s[start / 8 + 1];
|
||||
cr = s[start / 8 + 2];
|
||||
cc = (shiftR < 16) ? s[start / 8 + 1] : 0;
|
||||
cr = (shiftR < 8) ? s[start / 8 + 2] : 0;
|
||||
|
||||
x = ((long) (cl << 8 | cc) << 8 | cr) ; // Put bits together
|
||||
x = x >> (24 - (length + (start % 8))); // Right justify number
|
||||
x = x >> shiftR; // Right justify number
|
||||
x = ( x & (0xffff >> (16 - length) ) ); // Trim extra bits.
|
||||
|
||||
return x;
|
||||
|
||||
@@ -67,10 +67,9 @@ public:
|
||||
|
||||
struct Setup
|
||||
{
|
||||
bool auto_connect = true;
|
||||
Promote promote = Promote::automatic;
|
||||
std::shared_ptr<boost::asio::ssl::context> context;
|
||||
bool expire = false;
|
||||
beast::IP::Address public_ip;
|
||||
};
|
||||
|
||||
using PeerSequence = std::vector <Peer::ptr>;
|
||||
|
||||
@@ -218,7 +218,11 @@ ConnectAttempt::onHandshake (error_code ec)
|
||||
beast::http::message req = makeRequest(
|
||||
! overlay_.peerFinder().config().peerPrivate,
|
||||
remote_endpoint_.address());
|
||||
auto const hello = buildHello (sharedValue, app_);
|
||||
auto const hello = buildHello (
|
||||
sharedValue,
|
||||
overlay_.setup().public_ip,
|
||||
beast::IPAddressConversion::from_asio(remote_endpoint_),
|
||||
app_);
|
||||
appendHello (req, hello);
|
||||
|
||||
using beast::http::write;
|
||||
@@ -399,7 +403,10 @@ ConnectAttempt::processResponse (beast::http::message const& m,
|
||||
|
||||
RippleAddress publicKey;
|
||||
std::tie(publicKey, success) = verifyHello (hello,
|
||||
sharedValue, journal_, app_);
|
||||
sharedValue,
|
||||
overlay_.setup().public_ip,
|
||||
beast::IPAddressConversion::from_asio(remote_endpoint_),
|
||||
journal_, app_);
|
||||
if(! success)
|
||||
return close(); // verifyHello logs
|
||||
if(journal_.info) journal_.info <<
|
||||
|
||||
@@ -244,7 +244,10 @@ OverlayImpl::onHandoff (std::unique_ptr <beast::asio::ssl_bundle>&& ssl_bundle,
|
||||
|
||||
RippleAddress publicKey;
|
||||
std::tie(publicKey, success) = verifyHello (hello,
|
||||
sharedValue, journal, app_);
|
||||
sharedValue,
|
||||
setup_.public_ip,
|
||||
beast::IPAddressConversion::from_asio(
|
||||
remote_endpoint), journal, app_);
|
||||
if(! success)
|
||||
return handoff;
|
||||
|
||||
@@ -256,6 +259,7 @@ OverlayImpl::onHandoff (std::unique_ptr <beast::asio::ssl_bundle>&& ssl_bundle,
|
||||
publicKey.toPublicKey(), cluster);
|
||||
if (result != PeerFinder::Result::success)
|
||||
{
|
||||
m_peerFinder->on_closed(slot);
|
||||
if (journal.debug) journal.debug <<
|
||||
"Peer " << remote_endpoint << " redirected, slots full";
|
||||
handoff.moved = false;
|
||||
@@ -1017,17 +1021,20 @@ setup_Overlay (BasicConfig const& config)
|
||||
{
|
||||
Overlay::Setup setup;
|
||||
auto const& section = config.section("overlay");
|
||||
set (setup.auto_connect, "auto_connect", section);
|
||||
std::string promote;
|
||||
set (promote, "become_superpeer", section);
|
||||
if (promote == "never")
|
||||
setup.promote = Overlay::Promote::never;
|
||||
else if (promote == "always")
|
||||
setup.promote = Overlay::Promote::always;
|
||||
else
|
||||
setup.promote = Overlay::Promote::automatic;
|
||||
setup.context = make_SSLContext();
|
||||
setup.expire = get<bool>(section, "expire", false);
|
||||
|
||||
std::string ip;
|
||||
set (ip, "public_ip", section);
|
||||
if (! ip.empty ())
|
||||
{
|
||||
bool valid;
|
||||
std::tie (setup.public_ip, valid) =
|
||||
beast::IP::Address::from_string (ip);
|
||||
if (! valid || ! setup.public_ip.is_v4() ||
|
||||
is_private (setup.public_ip))
|
||||
throw std::runtime_error ("Configured public IP is invalid");
|
||||
}
|
||||
return setup;
|
||||
}
|
||||
|
||||
|
||||
@@ -596,7 +596,7 @@ void PeerImp::doAccept()
|
||||
|
||||
auto resp = makeResponse(
|
||||
! overlay_.peerFinder().config().peerPrivate,
|
||||
http_message_, sharedValue);
|
||||
http_message_, remote_address_, sharedValue);
|
||||
beast::http::write (write_buffer_, resp);
|
||||
|
||||
auto const protocol = BuildInfo::make_protocol(hello_.protoversion());
|
||||
@@ -636,7 +636,9 @@ void PeerImp::doAccept()
|
||||
|
||||
beast::http::message
|
||||
PeerImp::makeResponse (bool crawl,
|
||||
beast::http::message const& req, uint256 const& sharedValue)
|
||||
beast::http::message const& req,
|
||||
beast::IP::Endpoint remote,
|
||||
uint256 const& sharedValue)
|
||||
{
|
||||
beast::http::message resp;
|
||||
resp.request(false);
|
||||
@@ -648,7 +650,8 @@ PeerImp::makeResponse (bool crawl,
|
||||
resp.headers.append("Connect-AS", "Peer");
|
||||
resp.headers.append("Server", BuildInfo::getFullVersionString());
|
||||
resp.headers.append ("Crawl", crawl ? "public" : "private");
|
||||
protocol::TMHello hello = buildHello(sharedValue, app_);
|
||||
protocol::TMHello hello = buildHello(sharedValue,
|
||||
overlay_.setup().public_ip, remote, app_);
|
||||
appendHello(resp, hello);
|
||||
return resp;
|
||||
}
|
||||
@@ -1647,22 +1650,6 @@ PeerImp::sendGetPeers ()
|
||||
send (packet);
|
||||
}
|
||||
|
||||
bool
|
||||
PeerImp::sendHello()
|
||||
{
|
||||
bool success;
|
||||
std::tie(sharedValue_, success) = makeSharedValue(
|
||||
stream_.native_handle(), journal_);
|
||||
if (! success)
|
||||
return false;
|
||||
|
||||
auto const hello = buildHello (sharedValue_, app_);
|
||||
auto const m = std::make_shared<Message> (
|
||||
std::move(hello), protocol::mtHELLO);
|
||||
send (m);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
PeerImp::addLedger (uint256 const& hash)
|
||||
{
|
||||
|
||||
@@ -361,6 +361,7 @@ private:
|
||||
|
||||
beast::http::message
|
||||
makeResponse (bool crawl, beast::http::message const& req,
|
||||
beast::IP::Endpoint remoteAddress,
|
||||
uint256 const& sharedValue);
|
||||
|
||||
void
|
||||
@@ -440,15 +441,6 @@ private:
|
||||
void
|
||||
sendGetPeers();
|
||||
|
||||
/** Perform a secure handshake with the peer at the other end.
|
||||
If this function returns false then we cannot guarantee that there
|
||||
is no active man-in-the-middle attack taking place and the link
|
||||
MUST be disconnected.
|
||||
@return true if successful, false otherwise.
|
||||
*/
|
||||
bool
|
||||
sendHello();
|
||||
|
||||
void
|
||||
addLedger (uint256 const& hash);
|
||||
|
||||
|
||||
@@ -106,7 +106,11 @@ makeSharedValue (SSL* ssl, beast::Journal journal)
|
||||
}
|
||||
|
||||
protocol::TMHello
|
||||
buildHello (uint256 const& sharedValue, Application& app)
|
||||
buildHello (
|
||||
uint256 const& sharedValue,
|
||||
beast::IP::Address public_ip,
|
||||
beast::IP::Endpoint remote,
|
||||
Application& app)
|
||||
{
|
||||
protocol::TMHello h;
|
||||
|
||||
@@ -124,6 +128,18 @@ buildHello (uint256 const& sharedValue, Application& app)
|
||||
// h.set_ipv4port (portNumber); // ignored now
|
||||
h.set_testnet (false);
|
||||
|
||||
if (remote.is_v4())
|
||||
{
|
||||
auto addr = remote.to_v4 ();
|
||||
if (is_public (addr))
|
||||
{
|
||||
// Connection is to a public IP
|
||||
h.set_remote_ip (addr.value);
|
||||
if (public_ip != beast::IP::Address())
|
||||
h.set_local_ip (public_ip.to_v4().value);
|
||||
}
|
||||
}
|
||||
|
||||
// We always advertise ourselves as private in the HELLO message. This
|
||||
// suppresses the old peer advertising code and allows PeerFinder to
|
||||
// take over the functionality.
|
||||
@@ -168,6 +184,14 @@ appendHello (beast::http::message& m,
|
||||
if (hello.has_ledgerprevious())
|
||||
h.append ("Previous-Ledger", beast::base64_encode (
|
||||
hello.ledgerprevious()));
|
||||
|
||||
if (hello.has_local_ip())
|
||||
h.append ("Local-IP", beast::IP::to_string (
|
||||
beast::IP::AddressV4(hello.local_ip())));
|
||||
|
||||
if (hello.has_remote_ip())
|
||||
h.append ("Remote-IP", beast::IP::to_string (
|
||||
beast::IP::AddressV4(hello.remote_ip())));
|
||||
}
|
||||
|
||||
std::vector<ProtocolVersion>
|
||||
@@ -292,13 +316,47 @@ parseHello (beast::http::message const& m, beast::Journal journal)
|
||||
hello.set_ledgerprevious (beast::base64_decode (iter->second));
|
||||
}
|
||||
|
||||
{
|
||||
auto const iter = h.find ("Local-IP");
|
||||
if (iter != h.end())
|
||||
{
|
||||
bool valid;
|
||||
beast::IP::Address address;
|
||||
std::tie (address, valid) =
|
||||
beast::IP::Address::from_string (iter->second);
|
||||
if (!valid)
|
||||
return result;
|
||||
if (address.is_v4())
|
||||
hello.set_local_ip(address.to_v4().value);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
auto const iter = h.find ("Remote-IP");
|
||||
if (iter != h.end())
|
||||
{
|
||||
bool valid;
|
||||
beast::IP::Address address;
|
||||
std::tie (address, valid) =
|
||||
beast::IP::Address::from_string (iter->second);
|
||||
if (!valid)
|
||||
return result;
|
||||
if (address.is_v4())
|
||||
hello.set_remote_ip(address.to_v4().value);
|
||||
}
|
||||
}
|
||||
|
||||
result.second = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
std::pair<RippleAddress, bool>
|
||||
verifyHello (protocol::TMHello const& h, uint256 const& sharedValue,
|
||||
beast::Journal journal, Application& app)
|
||||
verifyHello (protocol::TMHello const& h,
|
||||
uint256 const& sharedValue,
|
||||
beast::IP::Address public_ip,
|
||||
beast::IP::Endpoint remote,
|
||||
beast::Journal journal,
|
||||
Application& app)
|
||||
{
|
||||
std::pair<RippleAddress, bool> result = { {}, false };
|
||||
auto const ourTime = app.timeKeeper().now().time_since_epoch().count();
|
||||
@@ -344,6 +402,11 @@ verifyHello (protocol::TMHello const& h, uint256 const& sharedValue,
|
||||
journal.info <<
|
||||
"Hello: Disconnect: Bad node public key.";
|
||||
}
|
||||
else if (result.first == app.getLocalCredentials().getNodePublic())
|
||||
{
|
||||
journal.info <<
|
||||
"Hello: Disconnect: Self connection.";
|
||||
}
|
||||
else if (! result.first.verifyNodePublic (
|
||||
sharedValue, h.nodeproof (), ECDSA::not_strict))
|
||||
{
|
||||
@@ -351,6 +414,31 @@ verifyHello (protocol::TMHello const& h, uint256 const& sharedValue,
|
||||
journal.info <<
|
||||
"Hello: Disconnect: Failed to verify session.";
|
||||
}
|
||||
else if (h.has_local_ip () &&
|
||||
is_public (remote) &&
|
||||
remote.is_v4 () &&
|
||||
(remote.to_v4().value != h.local_ip ()))
|
||||
{
|
||||
// Remote asked us to confirm connection is from
|
||||
// correct IP
|
||||
journal.info <<
|
||||
"Hello: Disconnect: Peer IP is " <<
|
||||
beast::IP::to_string (remote.to_v4())
|
||||
<< " not " <<
|
||||
beast::IP::to_string (beast::IP::AddressV4 (h.local_ip()));
|
||||
}
|
||||
else if (h.has_remote_ip() && is_public (remote) &&
|
||||
(public_ip != beast::IP::Address()) &&
|
||||
(h.remote_ip() != public_ip.to_v4().value))
|
||||
{
|
||||
// We know our public IP and peer reports connection
|
||||
// from some other IP
|
||||
journal.info <<
|
||||
"Hello: Disconnect: Our IP is " <<
|
||||
beast::IP::to_string (public_ip.to_v4())
|
||||
<< " not " <<
|
||||
beast::IP::to_string (beast::IP::AddressV4 (h.remote_ip()));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Successful connection.
|
||||
|
||||
@@ -52,7 +52,9 @@ makeSharedValue (SSL* ssl, beast::Journal journal);
|
||||
|
||||
/** Build a TMHello protocol message. */
|
||||
protocol::TMHello
|
||||
buildHello (uint256 const& sharedValue, Application& app);
|
||||
buildHello (uint256 const& sharedValue,
|
||||
beast::IP::Address public_ip,
|
||||
beast::IP::Endpoint remote, Application& app);
|
||||
|
||||
/** Insert HTTP headers based on the TMHello protocol message. */
|
||||
void
|
||||
@@ -70,6 +72,8 @@ parseHello (beast::http::message const& m, beast::Journal journal);
|
||||
*/
|
||||
std::pair<RippleAddress, bool>
|
||||
verifyHello (protocol::TMHello const& h, uint256 const& sharedValue,
|
||||
beast::IP::Address public_ip,
|
||||
beast::IP::Endpoint remote,
|
||||
beast::Journal journal, Application& app);
|
||||
|
||||
/** Parse a set of protocol versions.
|
||||
|
||||
@@ -95,6 +95,8 @@ message TMHello
|
||||
optional bool nodePrivate = 11; // Request to not forward IP.
|
||||
optional TMProofWork proofOfWork = 12; // request/provide proof of work
|
||||
optional bool testNet = 13; // Running as testnet.
|
||||
optional uint32 local_ip = 14; // our public IP
|
||||
optional uint32 remote_ip = 15; // IP we see connection from
|
||||
}
|
||||
|
||||
// The status of a node in our cluster
|
||||
|
||||
@@ -35,7 +35,7 @@ char const* getRawVersionString ()
|
||||
//
|
||||
// The build version number (edit this for each release)
|
||||
//
|
||||
"0.29.1-rc1"
|
||||
"0.30.0-hf1"
|
||||
//
|
||||
// Must follow the format described here:
|
||||
//
|
||||
|
||||
@@ -112,9 +112,6 @@ public:
|
||||
|
||||
Consumer newInboundEndpoint (beast::IP::Endpoint const& address)
|
||||
{
|
||||
if (isWhitelisted (address))
|
||||
return newAdminEndpoint (to_string (address));
|
||||
|
||||
Entry* entry (nullptr);
|
||||
|
||||
{
|
||||
@@ -146,9 +143,6 @@ public:
|
||||
|
||||
Consumer newOutboundEndpoint (beast::IP::Endpoint const& address)
|
||||
{
|
||||
if (isWhitelisted (address))
|
||||
return newAdminEndpoint (to_string (address));
|
||||
|
||||
Entry* entry (nullptr);
|
||||
|
||||
{
|
||||
@@ -370,14 +364,6 @@ public:
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
bool isWhitelisted (beast::IP::Endpoint const& address)
|
||||
{
|
||||
if (! is_public (address))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Called periodically to expire entries and groom the table.
|
||||
//
|
||||
void periodicActivity ()
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#include <ripple/server/Port.h>
|
||||
#include <ripple/json/json_value.h>
|
||||
#include <ripple/resource/ResourceManager.h>
|
||||
#include <beast/net/IPEndpoint.h>
|
||||
#include <vector>
|
||||
|
||||
@@ -47,6 +48,11 @@ Role
|
||||
requestRole (Role const& required, HTTP::Port const& port,
|
||||
Json::Value const& jsonRPC, beast::IP::Endpoint const& remoteIp);
|
||||
|
||||
Resource::Consumer
|
||||
requestInboundEndpoint (Resource::Manager& manager,
|
||||
beast::IP::Endpoint const& remoteAddress,
|
||||
HTTP::Port const& port);
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
|
||||
@@ -66,4 +66,15 @@ requestRole (Role const& required, HTTP::Port const& port,
|
||||
return role;
|
||||
}
|
||||
|
||||
Resource::Consumer
|
||||
requestInboundEndpoint (Resource::Manager& manager,
|
||||
beast::IP::Endpoint const& remoteAddress,
|
||||
HTTP::Port const& port)
|
||||
{
|
||||
if (requestRole (Role::GUEST, port, Json::Value(), remoteAddress) ==
|
||||
Role::ADMIN)
|
||||
return manager.newAdminEndpoint (to_string (remoteAddress));
|
||||
return manager.newInboundEndpoint(remoteAddress);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <ripple/rpc/Coroutine.h>
|
||||
#include <ripple/rpc/RPCHandler.h>
|
||||
#include <ripple/server/Port.h>
|
||||
#include <ripple/server/Role.h>
|
||||
#include <ripple/json/to_string.h>
|
||||
#include <ripple/rpc/RPCHandler.h>
|
||||
#include <ripple/rpc/Yield.h>
|
||||
@@ -133,8 +134,8 @@ ConnectionImpl <WebSocket>::ConnectionImpl (
|
||||
connection_ptr const& cpConnection,
|
||||
beast::IP::Endpoint const& remoteAddress,
|
||||
boost::asio::io_service& io_service)
|
||||
: InfoSub (source, // usage
|
||||
resourceManager.newInboundEndpoint (remoteAddress))
|
||||
: InfoSub (source, requestInboundEndpoint (
|
||||
resourceManager, remoteAddress, handler.port()))
|
||||
, app_(app)
|
||||
, m_port (handler.port ())
|
||||
, m_resourceManager (resourceManager)
|
||||
|
||||
Reference in New Issue
Block a user