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

Proposed 0.80.0-rc3 #2232

Merged
merged 8 commits into from
Sep 25, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ git-subtree. See the corresponding README for more details.

* [Ripple Knowledge Center](https://ripple.com/learn/)
* [Ripple Developer Center](https://ripple.com/build/)
* [Ripple Whitepapers & Reports](https://ripple.com/whitepapers-reports/)
* [Ripple Consensus Whitepaper](https://ripple.com/consensus-whitepaper/)
* Ripple Whitepapers & Reports
* [Ripple Consensus Whitepaper](https://ripple.com/files/ripple_consensus_whitepaper.pdf)
* [Ripple Solutions Guide](https://ripple.com/files/ripple_solutions_guide.pdf)

To learn about how Ripple is transforming global payments visit
Expand Down
15 changes: 15 additions & 0 deletions RELEASENOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,21 @@ If you are using Red Hat Enterprise Linux 7 or CentOS 7, you can [update using `

# Releases

## Version 0.70.2

The `rippled` 0.70.2 release corrects an emergent behavior which causes large numbers of transactions to get
stuck in different nodes' open ledgers without being passed on to validators, resulting in a spike in the open
ledger fee on those nodes.

**New and Updated Features**

This release has no new features.

**Bug Fixes**

- Recent fee rises and TxQ issues ([#2215](https://github.com/ripple/rippled/issues/2215))


## Version 0.70.1

The `rippled` 0.70.1 release corrects a technical flaw in the newly refactored consensus code that could cause a node to get stuck in consensus due to stale votes from a
Expand Down
6 changes: 6 additions & 0 deletions doc/rippled-example.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,12 @@
# time a transaction with a higher fee level is added.
# Default: 20.
#
# minimum_queue_size = <number>
#
# The queue will always be able to hold at least this <number> of
# transactions, regardless of recent ledger sizes or the value of
# ledgers_in_queue. Default: 2000.
#
# retry_sequence_percent = <number>
#
# If a client replaces a transaction in the queue (same sequence
Expand Down
17 changes: 15 additions & 2 deletions src/ripple/app/consensus/RCLConsensus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,9 @@ RCLConsensus::Adaptor::acquireLedger(LedgerHash const& ledger)
// Notify inbound transactions of the new ledger sequence number
inboundTransactions_.newRound(buildLCL->info().seq);

// Use the ledger timing rules of the acquired ledger
parms_.useRoundedCloseTime = buildLCL->rules().enabled(fix1528);

return RCLCxLedger(buildLCL);
}

Expand Down Expand Up @@ -152,6 +155,7 @@ RCLConsensus::Adaptor::relay(RCLCxTx const& tx)
// If we didn't relay this transaction recently, relay it to all peers
if (app_.getHashRouter().shouldRelay(tx.id()))
{
JLOG(j_.debug()) << "Relaying disputed tx " << tx.id();
auto const slice = tx.tx_.slice();
protocol::TMTransaction msg;
msg.set_rawtransaction(slice.data(), slice.size());
Expand All @@ -161,6 +165,10 @@ RCLConsensus::Adaptor::relay(RCLCxTx const& tx)
app_.overlay().foreach (send_always(
std::make_shared<Message>(msg, protocol::mtTRANSACTION)));
}
else
{
JLOG(j_.debug()) << "Not relaying disputed tx " << tx.id();
}
}
void
RCLConsensus::Adaptor::propose(RCLCxPeerPos::Proposal const& proposal)
Expand Down Expand Up @@ -301,6 +309,8 @@ RCLConsensus::Adaptor::onClose(
// Build SHAMap containing all transactions in our open ledger
for (auto const& tx : initialLedger->txs)
{
JLOG(j_.trace()) << "Adding open ledger TX " <<
tx.first->getTransactionID();
Serializer s(2048);
tx.first->add(s);
initialSet->addItem(
Expand Down Expand Up @@ -489,7 +499,7 @@ RCLConsensus::Adaptor::doAccept(
{
JLOG(j_.debug())
<< "Test applying disputed transaction that did"
<< " not get in";
<< " not get in " << it.second.tx().id();

SerialIter sit(it.second.tx().tx_.slice());
auto txn = std::make_shared<STTx const>(sit);
Expand Down Expand Up @@ -950,9 +960,12 @@ RCLConsensus::Adaptor::preStartRound(RCLCxLedger const & prevLgr)
JLOG(j_.info()) << "Entering consensus process, watching";
}

// Notify inbOund ledgers that we are starting a new round
// Notify inbound ledgers that we are starting a new round
inboundTransactions_.newRound(prevLgr.seq());

// Use parent ledger's rules to determine whether to use rounded close time
parms_.useRoundedCloseTime = prevLgr.ledger_->rules().enabled(fix1528);

// propose only if we're in sync with the network (and validating)
return validating_ &&
(app_.getOPs().getOperatingMode() == NetworkOPs::omFULL);
Expand Down
17 changes: 10 additions & 7 deletions src/ripple/app/ledger/OpenLedger.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ class OpenLedger
std::string const& suffix = "",
modify_type const& f = {});

private:
/** Algorithm for applying transactions.

This has the retry logic and ordering semantics
Expand All @@ -178,9 +179,9 @@ class OpenLedger
apply (Application& app, OpenView& view,
ReadView const& check, FwdRange const& txs,
OrderedTxs& retries, ApplyFlags flags,
beast::Journal j);
std::map<uint256, bool>& shouldRecover,
beast::Journal j);

private:
enum Result
{
success,
Expand All @@ -197,7 +198,7 @@ class OpenLedger
apply_one (Application& app, OpenView& view,
std::shared_ptr< STTx const> const& tx,
bool retry, ApplyFlags flags,
beast::Journal j);
bool shouldRecover, beast::Journal j);
};

//------------------------------------------------------------------------------
Expand All @@ -207,7 +208,8 @@ void
OpenLedger::apply (Application& app, OpenView& view,
ReadView const& check, FwdRange const& txs,
OrderedTxs& retries, ApplyFlags flags,
beast::Journal j)
std::map<uint256, bool>& shouldRecover,
beast::Journal j)
{
for (auto iter = txs.begin();
iter != txs.end(); ++iter)
Expand All @@ -217,10 +219,11 @@ OpenLedger::apply (Application& app, OpenView& view,
// Dereferencing the iterator can
// throw since it may be transformed.
auto const tx = *iter;
if (check.txExists(tx->getTransactionID()))
auto const txId = tx->getTransactionID();
if (check.txExists(txId))
continue;
auto const result = apply_one(app, view,
tx, true, flags, j);
tx, true, flags, shouldRecover[txId], j);
if (result == Result::retry)
retries.insert(tx);
}
Expand All @@ -241,7 +244,7 @@ OpenLedger::apply (Application& app, OpenView& view,
{
switch (apply_one(app, view,
iter->second, retry, flags,
j))
shouldRecover[iter->second->getTransactionID()], j))
{
case Result::success:
++changes;
Expand Down
69 changes: 63 additions & 6 deletions src/ripple/app/ledger/impl/OpenLedger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,13 @@
#include <BeastConfig.h>
#include <ripple/app/ledger/OpenLedger.h>
#include <ripple/app/main/Application.h>
#include <ripple/app/misc/HashRouter.h>
#include <ripple/app/misc/TxQ.h>
#include <ripple/app/tx/apply.h>
#include <ripple/ledger/CachedView.h>
#include <ripple/overlay/Message.h>
#include <ripple/overlay/Overlay.h>
#include <ripple/overlay/predicates.h>
#include <ripple/protocol/Feature.h>
#include <boost/range/adaptor/transformed.hpp>

Expand Down Expand Up @@ -84,14 +88,20 @@ OpenLedger::accept(Application& app, Rules const& rules,
JLOG(j_.trace()) <<
"accept ledger " << ledger->seq() << " " << suffix;
auto next = create(rules, ledger);
std::map<uint256, bool> shouldRecover;
if (retriesFirst)
{
for (auto const& tx : retries)
{
auto const txID = tx.second->getTransactionID();
shouldRecover[txID] = app.getHashRouter().shouldRecover(txID);
}
// Handle disputed tx, outside lock
using empty =
std::vector<std::shared_ptr<
STTx const>>;
apply (app, *next, *ledger, empty{},
retries, flags, j_);
retries, flags, shouldRecover, j_);
}
// Block calls to modify, otherwise
// new tx going into the open ledger
Expand All @@ -100,6 +110,19 @@ OpenLedger::accept(Application& app, Rules const& rules,
std::mutex> lock1(modify_mutex_);
// Apply tx from the current open view
if (! current_->txs.empty())
{
for (auto const& tx : current_->txs)
{
auto const txID = tx.first->getTransactionID();
auto iter = shouldRecover.lower_bound(txID);
if (iter != shouldRecover.end()
&& iter->first == txID)
// already had a chance via disputes
iter->second = false;
else
shouldRecover.emplace_hint(iter, txID,
app.getHashRouter().shouldRecover(txID));
}
apply (app, *next, *ledger,
boost::adaptors::transform(
current_->txs,
Expand All @@ -109,14 +132,38 @@ OpenLedger::accept(Application& app, Rules const& rules,
{
return p.first;
}),
retries, flags, j_);
retries, flags, shouldRecover, j_);
}
// Call the modifier
if (f)
f(*next, j_);
// Apply local tx
for (auto const& item : locals)
app.getTxQ().apply(app, *next,
item.second, flags, j_);

// If we didn't relay this transaction recently, relay it to all peers
for (auto const& txpair : next->txs)
{
auto const& tx = txpair.first;
auto const txId = tx->getTransactionID();
if (auto const toSkip = app.getHashRouter().shouldRelay(txId))
{
JLOG(j_.debug()) << "Relaying recovered tx " << txId;
protocol::TMTransaction msg;
Serializer s;

tx->add(s);
msg.set_rawtransaction(s.data(), s.size());
msg.set_status(protocol::tsNEW);
msg.set_receivetimestamp(
app.timeKeeper().now().time_since_epoch().count());
app.overlay().foreach(send_if_not(
std::make_shared<Message>(msg, protocol::mtTRANSACTION),
peer_in_set(*toSkip)));
}
}

// Switch to the new open view
std::lock_guard<
std::mutex> lock2(current_mutex_);
Expand All @@ -138,14 +185,24 @@ OpenLedger::create (Rules const& rules,
auto
OpenLedger::apply_one (Application& app, OpenView& view,
std::shared_ptr<STTx const> const& tx,
bool retry, ApplyFlags flags,
bool retry, ApplyFlags flags, bool shouldRecover,
beast::Journal j) -> Result
{
if (retry)
flags = flags | tapRETRY;
auto const result = ripple::apply(
app, view, *tx, flags, j);
if (result.second)
auto const result = [&]
{
auto const queueResult = app.getTxQ().apply(
app, view, tx, flags | tapPREFER_QUEUE, j);
// If the transaction can't get into the queue for intrinsic
// reasons, and it can still be recovered, try to put it
// directly into the open ledger, else drop it.
if (queueResult.first == telCAN_NOT_QUEUE && shouldRecover)
return ripple::apply(app, view, *tx, flags, j);
return queueResult;
}();
if (result.second ||
result.first == terQUEUED)
return Result::success;
if (isTefFailure (result.first) ||
isTemMalformed (result.first) ||
Expand Down
4 changes: 3 additions & 1 deletion src/ripple/app/main/Amendments.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@ supportedAmendments ()
{ "3012E8230864E95A58C60FD61430D7E1B4D3353195F2981DC12B0C7C0950FFAC FlowCross" },
{ "CC5ABAE4F3EC92E94A59B1908C2BE82D2228B6485C00AFF8F22DF930D89C194E SortedDirectories" },
{ "B4D44CC3111ADD964E846FC57760C8B50FFCD5A82C86A72756F6B058DDDF96AD fix1201" },
{ "6C92211186613F9647A89DFFBAB8F94C99D4C7E956D495270789128569177DA1 fix1512" }
{ "6C92211186613F9647A89DFFBAB8F94C99D4C7E956D495270789128569177DA1 fix1512" },
{ "B9E739B8296B4A1BB29BE990B17D66E21B62A300A909F25AC55C22D6C72E1F9D fix1523" },
{ "1D3463A5891F9E589C5AE839FFAC4A917CE96197098A1EF22304E1BC5B98A454 fix1528" }
};
}

Expand Down
3 changes: 2 additions & 1 deletion src/ripple/app/main/Application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,8 @@ class ApplicationImp
, mFeeTrack (std::make_unique<LoadFeeTrack>(logs_->journal("LoadManager")))

, mHashRouter (std::make_unique<HashRouter>(
stopwatch(), HashRouter::getDefaultHoldTime ()))
stopwatch(), HashRouter::getDefaultHoldTime (),
HashRouter::getDefaultRecoverLimit ()))

, mValidations (ValidationParms(),stopwatch(), logs_->journal("Validations"),
*this)
Expand Down
10 changes: 10 additions & 0 deletions src/ripple/app/misc/HashRouter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,4 +107,14 @@ HashRouter::shouldRelay (uint256 const& key)
return s.releasePeerSet();
}

bool
HashRouter::shouldRecover(uint256 const& key)
{
std::lock_guard <std::mutex> lock(mutex_);

auto& s = emplace(key).first;

return s.shouldRecover(recoverLimit_);
}

} // ripple
Loading