rippled
Loading...
Searching...
No Matches
overlay/Slot.h
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2012, 2013 Ripple Labs Inc.
5
6 Permission to use, copy, modify, and/or distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19
20#ifndef RIPPLE_OVERLAY_SLOT_H_INCLUDED
21#define RIPPLE_OVERLAY_SLOT_H_INCLUDED
22
23#include <xrpld/core/Config.h>
24#include <xrpld/overlay/Peer.h>
25#include <xrpld/overlay/ReduceRelayCommon.h>
26
27#include <xrpl/basics/Log.h>
28#include <xrpl/basics/chrono.h>
29#include <xrpl/basics/random.h>
30#include <xrpl/beast/container/aged_unordered_map.h>
31#include <xrpl/beast/utility/Journal.h>
32#include <xrpl/protocol/PublicKey.h>
33#include <xrpl/protocol/messages.h>
34
35#include <algorithm>
36#include <optional>
37#include <set>
38#include <tuple>
39#include <unordered_map>
40#include <unordered_set>
41
42namespace ripple {
43
44namespace reduce_relay {
45
46template <typename clock_type>
47class Slots;
48
50enum class PeerState : uint8_t {
51 Counting, // counting messages
52 Selected, // selected to relay, counting if Slot in Counting
53 Squelched, // squelched, doesn't relay
54};
56enum class SlotState : uint8_t {
57 Counting, // counting messages
58 Selected, // peers selected, stop counting
59};
60
61template <typename Unit, typename TP>
62Unit
63epoch(TP const& t)
64{
65 return std::chrono::duration_cast<Unit>(t.time_since_epoch());
66}
67
73{
74public:
76 {
77 }
83 virtual void
84 squelch(PublicKey const& validator, Peer::id_t id, std::uint32_t duration)
85 const = 0;
90 virtual void
91 unsquelch(PublicKey const& validator, Peer::id_t id) const = 0;
92};
93
104template <typename clock_type>
105class Slot final
106{
107private:
108 friend class Slots<clock_type>;
110 using time_point = typename clock_type::time_point;
111
112 // a callback to report ignored squelches
114
122 SquelchHandler const& handler,
123 beast::Journal journal,
124 uint16_t maxSelectedPeers)
126 , lastSelected_(clock_type::now())
128 , handler_(handler)
129 , journal_(journal)
130 , maxSelectedPeers_(maxSelectedPeers)
131 {
132 }
133
153 void
155 PublicKey const& validator,
156 id_t id,
157 protocol::MessageType type,
158 ignored_squelch_callback callback);
159
170 void
171 deletePeer(PublicKey const& validator, id_t id, bool erase);
172
174 time_point const&
176 {
177 return lastSelected_;
178 }
179
182 inState(PeerState state) const;
183
186 notInState(PeerState state) const;
187
190 getState() const
191 {
192 return state_;
193 }
194
197 getSelected() const;
198
202 std::
203 unordered_map<id_t, std::tuple<PeerState, uint16_t, uint32_t, uint32_t>>
204 getPeers() const;
205
212 void
213 deleteIdlePeer(PublicKey const& validator);
214
222
223private:
225 void
227
229 void
231
233 struct PeerInfo
234 {
235 PeerState state; // peer's state
236 std::size_t count; // message count
237 time_point expire; // squelch expiration time
238 time_point lastMessage; // time last message received
239 };
240
242
243 // pool of peers considered as the source of messages
244 // from validator - peers that reached MIN_MESSAGE_THRESHOLD
246
247 // number of peers that reached MAX_MESSAGE_THRESHOLD
249
250 // last time peers were selected, used to age the slot
251 typename clock_type::time_point lastSelected_;
252
253 SlotState state_; // slot's state
254 SquelchHandler const& handler_; // squelch/unsquelch handler
255 beast::Journal const journal_; // logging
256
257 // the maximum number of peers that should be selected as a validator
258 // message source
259 uint16_t const maxSelectedPeers_;
260};
261
262template <typename clock_type>
263void
265{
266 using namespace std::chrono;
267 auto now = clock_type::now();
268 for (auto it = peers_.begin(); it != peers_.end();)
269 {
270 auto& peer = it->second;
271 auto id = it->first;
272 ++it;
273 if (now - peer.lastMessage > IDLED)
274 {
275 JLOG(journal_.trace())
276 << "deleteIdlePeer: " << Slice(validator) << " " << id
277 << " idled "
278 << duration_cast<seconds>(now - peer.lastMessage).count()
279 << " selected " << (peer.state == PeerState::Selected);
280 deletePeer(validator, id, false);
281 }
282 }
283}
284
285template <typename clock_type>
286void
288 PublicKey const& validator,
289 id_t id,
290 protocol::MessageType type,
292{
293 using namespace std::chrono;
294 auto now = clock_type::now();
295 auto it = peers_.find(id);
296 // First message from this peer
297 if (it == peers_.end())
298 {
299 JLOG(journal_.trace())
300 << "update: adding peer " << Slice(validator) << " " << id;
301 peers_.emplace(
302 std::make_pair(id, PeerInfo{PeerState::Counting, 0, now, now}));
303 initCounting();
304 return;
305 }
306 // Message from a peer with expired squelch
307 if (it->second.state == PeerState::Squelched && now > it->second.expire)
308 {
309 JLOG(journal_.trace())
310 << "update: squelch expired " << Slice(validator) << " " << id;
311 it->second.state = PeerState::Counting;
312 it->second.lastMessage = now;
313 initCounting();
314 return;
315 }
316
317 auto& peer = it->second;
318
319 JLOG(journal_.trace())
320 << "update: existing peer " << Slice(validator) << " " << id
321 << " slot state " << static_cast<int>(state_) << " peer state "
322 << static_cast<int>(peer.state) << " count " << peer.count << " last "
323 << duration_cast<milliseconds>(now - peer.lastMessage).count()
324 << " pool " << considered_.size() << " threshold " << reachedThreshold_
325 << " " << (type == protocol::mtVALIDATION ? "validation" : "proposal");
326
327 peer.lastMessage = now;
328
329 // report if we received a message from a squelched peer
330 if (peer.state == PeerState::Squelched)
331 callback();
332
333 if (state_ != SlotState::Counting || peer.state == PeerState::Squelched)
334 return;
335
336 if (++peer.count > MIN_MESSAGE_THRESHOLD)
337 considered_.insert(id);
338 if (peer.count == (MAX_MESSAGE_THRESHOLD + 1))
339 ++reachedThreshold_;
340
341 if (now - lastSelected_ > 2 * MAX_UNSQUELCH_EXPIRE_DEFAULT)
342 {
343 JLOG(journal_.trace())
344 << "update: resetting due to inactivity " << Slice(validator) << " "
345 << id << " " << duration_cast<seconds>(now - lastSelected_).count();
346 initCounting();
347 return;
348 }
349
350 if (reachedThreshold_ == maxSelectedPeers_)
351 {
352 // Randomly select maxSelectedPeers_ peers from considered.
353 // Exclude peers that have been idling > IDLED -
354 // it's possible that deleteIdlePeer() has not been called yet.
355 // If number of remaining peers != maxSelectedPeers_
356 // then reset the Counting state and let deleteIdlePeer() handle
357 // idled peers.
359 auto const consideredPoolSize = considered_.size();
360 while (selected.size() != maxSelectedPeers_ && considered_.size() != 0)
361 {
362 auto i =
363 considered_.size() == 1 ? 0 : rand_int(considered_.size() - 1);
364 auto it = std::next(considered_.begin(), i);
365 auto id = *it;
366 considered_.erase(it);
367 auto const& itpeers = peers_.find(id);
368 if (itpeers == peers_.end())
369 {
370 JLOG(journal_.error()) << "update: peer not found "
371 << Slice(validator) << " " << id;
372 continue;
373 }
374 if (now - itpeers->second.lastMessage < IDLED)
375 selected.insert(id);
376 }
377
378 if (selected.size() != maxSelectedPeers_)
379 {
380 JLOG(journal_.trace())
381 << "update: selection failed " << Slice(validator) << " " << id;
382 initCounting();
383 return;
384 }
385
386 lastSelected_ = now;
387
388 auto s = selected.begin();
389 JLOG(journal_.trace())
390 << "update: " << Slice(validator) << " " << id << " pool size "
391 << consideredPoolSize << " selected " << *s << " "
392 << *std::next(s, 1) << " " << *std::next(s, 2);
393
394 XRPL_ASSERT(
395 peers_.size() >= maxSelectedPeers_,
396 "ripple::reduce_relay::Slot::update : minimum peers");
397
398 // squelch peers which are not selected and
399 // not already squelched
401 for (auto& [k, v] : peers_)
402 {
403 v.count = 0;
404
405 if (selected.find(k) != selected.end())
406 v.state = PeerState::Selected;
407 else if (v.state != PeerState::Squelched)
408 {
409 if (journal_.trace())
410 str << k << " ";
411 v.state = PeerState::Squelched;
413 getSquelchDuration(peers_.size() - maxSelectedPeers_);
414 v.expire = now + duration;
415 handler_.squelch(validator, k, duration.count());
416 }
417 }
418 JLOG(journal_.trace()) << "update: squelching " << Slice(validator)
419 << " " << id << " " << str.str();
420 considered_.clear();
421 reachedThreshold_ = 0;
422 state_ = SlotState::Selected;
423 }
424}
425
426template <typename clock_type>
429{
430 using namespace std::chrono;
431 auto m = std::max(
434 {
436 JLOG(journal_.warn())
437 << "getSquelchDuration: unexpected squelch duration " << npeers;
438 }
439 return seconds{ripple::rand_int(MIN_UNSQUELCH_EXPIRE / 1s, m / 1s)};
440}
441
442template <typename clock_type>
443void
445{
446 auto it = peers_.find(id);
447 if (it != peers_.end())
448 {
449 JLOG(journal_.trace())
450 << "deletePeer: " << Slice(validator) << " " << id << " selected "
451 << (it->second.state == PeerState::Selected) << " considered "
452 << (considered_.find(id) != considered_.end()) << " erase "
453 << erase;
454 auto now = clock_type::now();
455 if (it->second.state == PeerState::Selected)
456 {
457 for (auto& [k, v] : peers_)
458 {
459 if (v.state == PeerState::Squelched)
460 handler_.unsquelch(validator, k);
461 v.state = PeerState::Counting;
462 v.count = 0;
463 v.expire = now;
464 }
465
466 considered_.clear();
467 reachedThreshold_ = 0;
468 state_ = SlotState::Counting;
469 }
470 else if (considered_.find(id) != considered_.end())
471 {
472 if (it->second.count > MAX_MESSAGE_THRESHOLD)
473 --reachedThreshold_;
474 considered_.erase(id);
475 }
476
477 it->second.lastMessage = now;
478 it->second.count = 0;
479
480 if (erase)
481 peers_.erase(it);
482 }
483}
484
485template <typename clock_type>
486void
488{
489 for (auto& [_, peer] : peers_)
490 {
491 (void)_;
492 peer.count = 0;
493 }
494}
495
496template <typename clock_type>
497void
499{
500 state_ = SlotState::Counting;
501 considered_.clear();
502 reachedThreshold_ = 0;
503 resetCounts();
504}
505
506template <typename clock_type>
509{
510 return std::count_if(peers_.begin(), peers_.end(), [&](auto const& it) {
511 return (it.second.state == state);
512 });
513}
514
515template <typename clock_type>
518{
519 return std::count_if(peers_.begin(), peers_.end(), [&](auto const& it) {
520 return (it.second.state != state);
521 });
522}
523
524template <typename clock_type>
527{
529 for (auto const& [id, info] : peers_)
530 if (info.state == PeerState::Selected)
531 r.insert(id);
532 return r;
533}
534
535template <typename clock_type>
537 typename Peer::id_t,
540{
541 using namespace std::chrono;
542 auto r = std::unordered_map<
543 id_t,
545
546 for (auto const& [id, info] : peers_)
547 r.emplace(std::make_pair(
548 id,
549 std::move(std::make_tuple(
550 info.state,
551 info.count,
552 epoch<milliseconds>(info.expire).count(),
553 epoch<milliseconds>(info.lastMessage).count()))));
554
555 return r;
556}
557
562template <typename clock_type>
563class Slots final
564{
565 using time_point = typename clock_type::time_point;
566 using id_t = typename Peer::id_t;
568 uint256,
570 clock_type,
572
573public:
579 Slots(Logs& logs, SquelchHandler const& handler, Config const& config)
580 : handler_(handler)
581 , logs_(logs)
582 , journal_(logs.journal("Slots"))
583 , baseSquelchEnabled_(config.VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE)
584 , maxSelectedPeers_(config.VP_REDUCE_RELAY_SQUELCH_MAX_SELECTED_PEERS)
585 {
586 }
587 ~Slots() = default;
588
590 bool
592 {
594 }
595
597 bool
599 {
602 reduce_relay::epoch<std::chrono::minutes>(clock_type::now()) >
604
605 return reduceRelayReady_;
606 }
607
615 void
617 uint256 const& key,
618 PublicKey const& validator,
619 id_t id,
620 protocol::MessageType type)
621 {
622 updateSlotAndSquelch(key, validator, id, type, []() {});
623 }
624
632 void
634 uint256 const& key,
635 PublicKey const& validator,
636 id_t id,
637 protocol::MessageType type,
639
643 void
645
648 inState(PublicKey const& validator, PeerState state) const
649 {
650 auto const& it = slots_.find(validator);
651 if (it != slots_.end())
652 return it->second.inState(state);
653 return {};
654 }
655
658 notInState(PublicKey const& validator, PeerState state) const
659 {
660 auto const& it = slots_.find(validator);
661 if (it != slots_.end())
662 return it->second.notInState(state);
663 return {};
664 }
665
667 bool
668 inState(PublicKey const& validator, SlotState state) const
669 {
670 auto const& it = slots_.find(validator);
671 if (it != slots_.end())
672 return it->second.state_ == state;
673 return false;
674 }
675
678 getSelected(PublicKey const& validator)
679 {
680 auto const& it = slots_.find(validator);
681 if (it != slots_.end())
682 return it->second.getSelected();
683 return {};
684 }
685
690 typename Peer::id_t,
692 getPeers(PublicKey const& validator)
693 {
694 auto const& it = slots_.find(validator);
695 if (it != slots_.end())
696 return it->second.getPeers();
697 return {};
698 }
699
702 getState(PublicKey const& validator)
703 {
704 auto const& it = slots_.find(validator);
705 if (it != slots_.end())
706 return it->second.getState();
707 return {};
708 }
709
716 void
718
719private:
723 bool
724 addPeerMessage(uint256 const& key, id_t id);
725
727
729 SquelchHandler const& handler_; // squelch/unsquelch handler
732
735
736 // Maintain aged container of message/peers. This is required
737 // to discard duplicate message from the same peer. A message
738 // is aged after IDLED seconds. A message received IDLED seconds
739 // after it was relayed is ignored by PeerImp.
741 beast::get_abstract_clock<clock_type>()};
742};
743
744template <typename clock_type>
745bool
747{
748 beast::expire(peersWithMessage_, reduce_relay::IDLED);
749
750 if (key.isNonZero())
751 {
752 auto it = peersWithMessage_.find(key);
753 if (it == peersWithMessage_.end())
754 {
755 JLOG(journal_.trace())
756 << "addPeerMessage: new " << to_string(key) << " " << id;
757 peersWithMessage_.emplace(key, std::unordered_set<id_t>{id});
758 return true;
759 }
760
761 if (it->second.find(id) != it->second.end())
762 {
763 JLOG(journal_.trace()) << "addPeerMessage: duplicate message "
764 << to_string(key) << " " << id;
765 return false;
766 }
767
768 JLOG(journal_.trace())
769 << "addPeerMessage: added " << to_string(key) << " " << id;
770
771 it->second.insert(id);
772 }
773
774 return true;
775}
776
777template <typename clock_type>
778void
780 uint256 const& key,
781 PublicKey const& validator,
782 id_t id,
783 protocol::MessageType type,
785{
786 if (!addPeerMessage(key, id))
787 return;
788
789 auto it = slots_.find(validator);
790 if (it == slots_.end())
791 {
792 JLOG(journal_.trace())
793 << "updateSlotAndSquelch: new slot " << Slice(validator);
794 auto it =
795 slots_
796 .emplace(std::make_pair(
797 validator,
799 handler_, logs_.journal("Slot"), maxSelectedPeers_)))
800 .first;
801 it->second.update(validator, id, type, callback);
802 }
803 else
804 it->second.update(validator, id, type, callback);
805}
806
807template <typename clock_type>
808void
810{
811 for (auto& [validator, slot] : slots_)
812 slot.deletePeer(validator, id, erase);
813}
814
815template <typename clock_type>
816void
818{
819 auto now = clock_type::now();
820
821 for (auto it = slots_.begin(); it != slots_.end();)
822 {
823 it->second.deleteIdlePeer(it->first);
824 if (now - it->second.getLastSelected() > MAX_UNSQUELCH_EXPIRE_DEFAULT)
825 {
826 JLOG(journal_.trace())
827 << "deleteIdlePeers: deleting idle slot " << Slice(it->first);
828 it = slots_.erase(it);
829 }
830 else
831 ++it;
832 }
833}
834
835} // namespace reduce_relay
836
837} // namespace ripple
838
839#endif // RIPPLE_OVERLAY_SLOT_H_INCLUDED
T begin(T... args)
A generic endpoint for log messages.
Definition: Journal.h:60
Associative container where each element is also indexed by time.
Manages partitions for logging.
Definition: Log.h:51
std::uint32_t id_t
Uniquely identifies a peer.
A public key.
Definition: PublicKey.h:61
An immutable linear range of bytes.
Definition: Slice.h:46
std::size_t size() const noexcept
Returns the number of bytes in the storage.
Definition: Slice.h:81
bool isNonZero() const
Definition: base_uint.h:545
Seed functor once per construction.
Definition: hardened_hash.h:93
Slot is associated with a specific validator via validator's public key.
Definition: overlay/Slot.h:106
std::unordered_map< id_t, std::tuple< PeerState, uint16_t, uint32_t, uint32_t > > getPeers() const
Get peers info.
Definition: overlay/Slot.h:539
Slot(SquelchHandler const &handler, beast::Journal journal, uint16_t maxSelectedPeers)
Constructor.
Definition: overlay/Slot.h:121
void deletePeer(PublicKey const &validator, id_t id, bool erase)
Handle peer deletion when a peer disconnects.
Definition: overlay/Slot.h:444
std::uint16_t reachedThreshold_
Definition: overlay/Slot.h:248
uint16_t const maxSelectedPeers_
Definition: overlay/Slot.h:259
std::uint16_t notInState(PeerState state) const
Return number of peers not in state.
Definition: overlay/Slot.h:517
typename clock_type::time_point time_point
Definition: overlay/Slot.h:110
SquelchHandler const & handler_
Definition: overlay/Slot.h:254
void initCounting()
Initialize slot to Counting state.
Definition: overlay/Slot.h:498
time_point const & getLastSelected() const
Get the time of the last peer selection round.
Definition: overlay/Slot.h:175
clock_type::time_point lastSelected_
Definition: overlay/Slot.h:251
void update(PublicKey const &validator, id_t id, protocol::MessageType type, ignored_squelch_callback callback)
Update peer info.
Definition: overlay/Slot.h:287
std::set< id_t > getSelected() const
Return selected peers.
Definition: overlay/Slot.h:526
SlotState getState() const
Return Slot's state.
Definition: overlay/Slot.h:190
std::uint16_t inState(PeerState state) const
Return number of peers in state.
Definition: overlay/Slot.h:508
void deleteIdlePeer(PublicKey const &validator)
Check if peers stopped relaying messages.
Definition: overlay/Slot.h:264
std::unordered_set< id_t > considered_
Definition: overlay/Slot.h:245
std::chrono::seconds getSquelchDuration(std::size_t npeers)
Get random squelch duration between MIN_UNSQUELCH_EXPIRE and min(max(MAX_UNSQUELCH_EXPIRE_DEFAULT,...
Definition: overlay/Slot.h:428
std::unordered_map< id_t, PeerInfo > peers_
Definition: overlay/Slot.h:241
void resetCounts()
Reset counts of peers in Selected or Counting state.
Definition: overlay/Slot.h:487
beast::Journal const journal_
Definition: overlay/Slot.h:255
Slots is a container for validator's Slot and handles Slot update when a message is received from a v...
Definition: overlay/Slot.h:564
typename clock_type::time_point time_point
Definition: overlay/Slot.h:565
bool reduceRelayReady()
Check if reduce_relay::WAIT_ON_BOOTUP time passed since startup.
Definition: overlay/Slot.h:598
static messages peersWithMessage_
Definition: overlay/Slot.h:740
void deletePeer(id_t id, bool erase)
Called when a peer is deleted.
Definition: overlay/Slot.h:809
void deleteIdlePeers()
Check if peers stopped relaying messages and if slots stopped receiving messages from the validator.
Definition: overlay/Slot.h:817
bool addPeerMessage(uint256 const &key, id_t id)
Add message/peer if have not seen this message from the peer.
Definition: overlay/Slot.h:746
beast::Journal const journal_
Definition: overlay/Slot.h:731
std::optional< std::uint16_t > notInState(PublicKey const &validator, PeerState state) const
Return number of peers not in state.
Definition: overlay/Slot.h:658
std::set< id_t > getSelected(PublicKey const &validator)
Get selected peers.
Definition: overlay/Slot.h:678
bool baseSquelchReady()
Check if base squelching feature is enabled and ready.
Definition: overlay/Slot.h:591
hash_map< PublicKey, Slot< clock_type > > slots_
Definition: overlay/Slot.h:728
std::optional< std::uint16_t > inState(PublicKey const &validator, PeerState state) const
Return number of peers in state.
Definition: overlay/Slot.h:648
bool inState(PublicKey const &validator, SlotState state) const
Return true if Slot is in state.
Definition: overlay/Slot.h:668
std::unordered_map< typename Peer::id_t, std::tuple< PeerState, uint16_t, uint32_t, std::uint32_t > > getPeers(PublicKey const &validator)
Get peers info.
Definition: overlay/Slot.h:692
uint16_t const maxSelectedPeers_
Definition: overlay/Slot.h:734
std::optional< SlotState > getState(PublicKey const &validator)
Get Slot's state.
Definition: overlay/Slot.h:702
void updateSlotAndSquelch(uint256 const &key, PublicKey const &validator, id_t id, protocol::MessageType type, typename Slot< clock_type >::ignored_squelch_callback callback)
Calls Slot::update of Slot associated with the validator.
Definition: overlay/Slot.h:779
std::atomic_bool reduceRelayReady_
Definition: overlay/Slot.h:726
void updateSlotAndSquelch(uint256 const &key, PublicKey const &validator, id_t id, protocol::MessageType type)
Calls Slot::update of Slot associated with the validator, with a noop callback.
Definition: overlay/Slot.h:616
Slots(Logs &logs, SquelchHandler const &handler, Config const &config)
Definition: overlay/Slot.h:579
SquelchHandler const & handler_
Definition: overlay/Slot.h:729
typename Peer::id_t id_t
Definition: overlay/Slot.h:566
virtual void unsquelch(PublicKey const &validator, Peer::id_t id) const =0
Unsquelch handler.
virtual void squelch(PublicKey const &validator, Peer::id_t id, std::uint32_t duration) const =0
Squelch handler.
T end(T... args)
T find(T... args)
T insert(T... args)
T make_pair(T... args)
T make_tuple(T... args)
T max(T... args)
std::enable_if< is_aged_container< AgedContainer >::value, std::size_t >::type expire(AgedContainer &c, std::chrono::duration< Rep, Period > const &age)
Expire aged container items past the specified age.
static constexpr auto SQUELCH_PER_PEER
Unit epoch(TP const &t)
Definition: overlay/Slot.h:63
static constexpr auto MIN_UNSQUELCH_EXPIRE
SlotState
Slot's State.
Definition: overlay/Slot.h:56
static constexpr auto IDLED
PeerState
Peer's State.
Definition: overlay/Slot.h:50
static constexpr uint16_t MAX_MESSAGE_THRESHOLD
static constexpr auto WAIT_ON_BOOTUP
static constexpr auto MAX_UNSQUELCH_EXPIRE_DEFAULT
static constexpr uint16_t MIN_MESSAGE_THRESHOLD
static constexpr auto MAX_UNSQUELCH_EXPIRE_PEERS
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: algorithm.h:25
std::enable_if_t< std::is_integral< Integral >::value, Integral > rand_int()
base_uint< 256 > uint256
Definition: base_uint.h:558
void erase(STObject &st, TypedField< U > const &f)
Remove a field in an STObject.
Definition: STExchange.h:172
std::string to_string(base_uint< Bits, Tag > const &a)
Definition: base_uint.h:630
T next(T... args)
T size(T... args)
T str(T... args)
Data maintained for each peer.
Definition: overlay/Slot.h:234