Merge master (1.1.2) into develop (1.2.0-b8)

This commit is contained in:
Nik Bougalis
2018-12-11 12:48:32 -08:00
6 changed files with 237 additions and 170 deletions

View File

@@ -29,7 +29,7 @@
namespace ripple {
/** The tip of a span of ledger ancestry
*/
*/
template <class Ledger>
class SpanTip
{
@@ -461,7 +461,7 @@ public:
newNode->branchSupport = loc->branchSupport;
newNode->children = std::move(loc->children);
assert(loc->children.empty());
for(std::unique_ptr<Node> & child : newNode->children)
for (std::unique_ptr<Node>& child : newNode->children)
child->parent = newNode.get();
// Loc truncates to prefix and newNode is its child
@@ -512,8 +512,7 @@ public:
Seq diffSeq;
std::tie(loc, diffSeq) = find(ledger);
// Cannot erase root
if (loc && loc != root.get())
if (loc)
{
// Must be exact match with tip support
if (diffSeq == loc->span.end() && diffSeq > ledger.seq() &&
@@ -525,7 +524,7 @@ public:
auto const it = seqSupport.find(ledger.seq());
assert(it != seqSupport.end() && it->second >= count);
it->second -= count;
if(it->second == 0)
if (it->second == 0)
seqSupport.erase(it->first);
Node* decNode = loc;
@@ -584,7 +583,8 @@ public:
/** Return the count of branch support for the specific ledger
@param ledger The ledger to lookup
@return The number of entries in the trie for this ledger or a descendant
@return The number of entries in the trie for this ledger or a
descendant
*/
std::uint32_t
branchSupport(Ledger const& ledger) const
@@ -595,8 +595,7 @@ public:
// Check that ledger is is an exact match or proper
// prefix of loc
if (loc && diffSeq > ledger.seq() &&
ledger.seq() < loc->span.end())
if (loc && diffSeq > ledger.seq() && ledger.seq() < loc->span.end())
{
return loc->branchSupport;
}
@@ -659,11 +658,15 @@ public:
@param largestIssued The sequence number of the largest validation
issued by this node.
@return Pair with the sequence number and ID of the preferred ledger
@return Pair with the sequence number and ID of the preferred ledger or
boost::none if no preferred ledger exists
*/
SpanTip<Ledger>
boost::optional<SpanTip<Ledger>>
getPreferred(Seq const largestIssued) const
{
if (empty())
return boost::none;
Node* curr = root.get();
bool done = false;
@@ -699,7 +702,7 @@ public:
uncommitted += uncommittedIt->second;
uncommittedIt++;
}
else // otherwise we jump to the end of the span
else // otherwise we jump to the end of the span
nextSeq = curr->span.end();
}
// We did not consume the entire span, so we have found the
@@ -727,8 +730,10 @@ public:
curr->children.end(),
[](std::unique_ptr<Node> const& a,
std::unique_ptr<Node> const& b) {
return std::make_tuple(a->branchSupport, a->span.startID()) >
std::make_tuple(b->branchSupport, b->span.startID());
return std::make_tuple(
a->branchSupport, a->span.startID()) >
std::make_tuple(
b->branchSupport, b->span.startID());
});
best = curr->children[0].get();
@@ -752,6 +757,14 @@ public:
return curr->span.tip();
}
/** Return whether the trie is tracking any ledgers
*/
bool
empty() const
{
return !root || root->branchSupport == 0;
}
/** Dump an ascii representation of the trie to the stream
*/
void
@@ -761,7 +774,7 @@ public:
}
/** Dump JSON representation of trie state
*/
*/
Json::Value
getJson() const
{
@@ -798,7 +811,7 @@ public:
for (auto const& child : curr->children)
{
if(child->parent != curr)
if (child->parent != curr)
return false;
support += child->branchSupport;

View File

@@ -87,6 +87,7 @@ class SeqEnforcer
using time_point = std::chrono::steady_clock::time_point;
Seq seq_{0};
time_point when_;
public:
/** Try advancing the largest observed validation ledger sequence
@@ -101,11 +102,11 @@ public:
@return Whether the validation satisfies the invariant
*/
bool
operator()(time_point now, Seq s, ValidationParms const & p)
operator()(time_point now, Seq s, ValidationParms const& p)
{
if(now > (when_ + p.validationSET_EXPIRES))
if (now > (when_ + p.validationSET_EXPIRES))
seq_ = Seq{0};
if(s <= seq_)
if (s <= seq_)
return false;
seq_ = s;
when_ = now;
@@ -147,7 +148,6 @@ isCurrent(
(seenTime < (now + p.validationCURRENT_LOCAL)));
}
/** Status of newly received validation
*/
enum class ValStatus {
@@ -233,8 +233,8 @@ to_string(ValStatus m)
// Whether this is a full or partial validation
bool full() const;
// Identifier for this node that remains fixed even when rotating signing
// keys
// Identifier for this node that remains fixed even when rotating
// signing keys
NodeID nodeID() const;
implementation_specific_t
@@ -312,7 +312,7 @@ class Validations
hash_map<NodeID, Ledger> lastLedger_;
// Set of ledgers being acquired from the network
hash_map<std::pair<Seq,ID>, hash_set<NodeID>> acquiring_;
hash_map<std::pair<Seq, ID>, hash_set<NodeID>> acquiring_;
// Parameters to determine validation staleness
ValidationParms const parms_;
@@ -327,7 +327,8 @@ private:
removeTrie(ScopedLock const&, NodeID const& nodeID, Validation const& val)
{
{
auto it = acquiring_.find(std::make_pair(val.seq(), val.ledgerID()));
auto it =
acquiring_.find(std::make_pair(val.seq(), val.ledgerID()));
if (it != acquiring_.end())
{
it->second.erase(nodeID);
@@ -387,7 +388,8 @@ private:
@param lock Existing lock of mutex_
@param nodeID The node identifier of the validating node
@param val The trusted validation issued by the node
@param prior If not none, the last current validated ledger Seq,ID of key
@param prior If not none, the last current validated ledger Seq,ID of
key
*/
void
updateTrie(
@@ -445,7 +447,7 @@ private:
withTrie(ScopedLock const& lock, F&& f)
{
// Call current to flush any stale validations
current(lock, [](auto){}, [](auto, auto){});
current(lock, [](auto) {}, [](auto, auto) {});
checkAcquired(lock);
return f(trie_);
}
@@ -537,8 +539,8 @@ public:
}
/** Return the adaptor instance
*/
Adaptor const &
*/
Adaptor const&
adaptor() const
{
return adaptor_;
@@ -552,8 +554,8 @@ public:
return parms_;
}
/** Return whether the local node can issue a validation for the given sequence
number
/** Return whether the local node can issue a validation for the given
sequence number
@param s The sequence number of the ledger the node wants to validate
@return Whether the validation satisfies the invariant, updating the
@@ -602,7 +604,7 @@ public:
Validation& oldVal = ins.first->second;
if (val.signTime() > oldVal.signTime())
{
std::pair<Seq,ID> old(oldVal.seq(),oldVal.ledgerID());
std::pair<Seq, ID> old(oldVal.seq(), oldVal.ledgerID());
adaptor_.onStale(std::move(oldVal));
ins.first->second = val;
if (val.trusted())
@@ -691,20 +693,19 @@ public:
@param curr The local node's current working ledger
@return The sequence and id of the preferred working ledger,
or Seq{0},ID{0} if no trusted validations are available to
or boost::none if no trusted validations are available to
determine the preferred ledger.
*/
std::pair<Seq, ID>
boost::optional<std::pair<Seq, ID>>
getPreferred(Ledger const& curr)
{
ScopedLock lock{mutex_};
SpanTip<Ledger> preferred =
boost::optional<SpanTip<Ledger>> preferred =
withTrie(lock, [this](LedgerTrie<Ledger>& trie) {
return trie.getPreferred(localSeqEnforcer_.largest());
});
// No trusted validations to determine branch
if (preferred.seq == Seq{0})
if (!preferred)
{
// fall back to majority over acquiring ledgers
auto it = std::max_element(
@@ -722,26 +723,26 @@ public:
return std::tie(aSize, aKey.second) <
std::tie(bSize, bKey.second);
});
if(it != acquiring_.end())
if (it != acquiring_.end())
return it->first;
return std::make_pair(preferred.seq, preferred.id);
return boost::none;
}
// If we are the parent of the preferred ledger, stick with our
// current ledger since we might be about to generate it
if (preferred.seq == curr.seq() + Seq{1} &&
preferred.ancestor(curr.seq()) == curr.id())
if (preferred->seq == curr.seq() + Seq{1} &&
preferred->ancestor(curr.seq()) == curr.id())
return std::make_pair(curr.seq(), curr.id());
// A ledger ahead of us is preferred regardless of whether it is
// a descendant of our working ledger or it is on a different chain
if (preferred.seq > curr.seq())
return std::make_pair(preferred.seq, preferred.id);
if (preferred->seq > curr.seq())
return std::make_pair(preferred->seq, preferred->id);
// Only switch to earlier or same sequence number
// if it is a different chain.
if (curr[preferred.seq] != preferred.id)
return std::make_pair(preferred.seq, preferred.id);
if (curr[preferred->seq] != preferred->id)
return std::make_pair(preferred->seq, preferred->id);
// Stick with current ledger
return std::make_pair(curr.seq(), curr.id());
@@ -759,22 +760,21 @@ public:
ID
getPreferred(Ledger const& curr, Seq minValidSeq)
{
std::pair<Seq, ID> preferred = getPreferred(curr);
if(preferred.first >= minValidSeq && preferred.second != ID{0})
return preferred.second;
boost::optional<std::pair<Seq, ID>> preferred = getPreferred(curr);
if (preferred && preferred->first >= minValidSeq)
return preferred->second;
return curr.id();
}
/** Determine the preferred last closed ledger for the next consensus round.
Called before starting the next round of ledger consensus to determine the
preferred working ledger. Uses the dominant peerCount ledger if no
Called before starting the next round of ledger consensus to determine
the preferred working ledger. Uses the dominant peerCount ledger if no
trusted validations are available.
@param lcl Last closed ledger by this node
@param minSeq Minimum allowed sequence number of the trusted preferred ledger
@param minSeq Minimum allowed sequence number of the trusted preferred
ledger
@param peerCounts Map from ledger ids to count of peers with that as the
last closed ledger
@return The preferred last closed ledger ID
@@ -784,15 +784,16 @@ public:
*/
ID
getPreferredLCL(
Ledger const & lcl,
Ledger const& lcl,
Seq minSeq,
hash_map<ID, std::uint32_t> const& peerCounts)
{
std::pair<Seq, ID> preferred = getPreferred(lcl);
boost::optional<std::pair<Seq, ID>> preferred = getPreferred(lcl);
// Trusted validations exist
if (preferred.second != ID{0} && preferred.first > Seq{0})
return (preferred.first >= minSeq) ? preferred.second : lcl.id();
// Trusted validations exist, but stick with local preferred ledger if
// preferred is in the past
if (preferred)
return (preferred->first >= minSeq) ? preferred->second : lcl.id();
// Otherwise, rely on peer ledgers
auto it = std::max_element(

View File

@@ -392,6 +392,11 @@ public:
if (keys_.find (key) != keys_.end())
return Result::duplicate;
// If the peer belongs to a cluster, update the slot to reflect that.
counts_.remove (*slot);
slot->cluster (cluster);
counts_.add (*slot);
// See if we have an open space for this slot
if (! counts_.can_activate (*slot))
{
@@ -401,18 +406,15 @@ public:
return Result::full;
}
// Set key and cluster right before adding to the map
// otherwise we could assert later when erasing the key.
counts_.remove (*slot);
// Set the key right before adding to the map, otherwise we might
// assert later when erasing the key.
slot->public_key (key);
slot->cluster (cluster);
counts_.add (*slot);
// Add the public key to the active set
auto const result = keys_.insert (key);
// Public key must not already exist
assert (result.second);
(void) result.second;
{
auto const result = keys_.insert(key);
// Public key must not already exist
assert (result.second);
(void)result.second;
}
// Change state and update counts
counts_.remove (*slot);