Kagome
Polkadot Runtime Engine in C++17
reputation_repository_impl.cpp
Go to the documentation of this file.
1 
7 
8 #include <boost/assert.hpp>
9 
11 
12 using namespace std::chrono_literals;
13 
14 namespace kagome::network {
15 
16  ReputationRepositoryImpl::ReputationRepositoryImpl(
17  std::shared_ptr<libp2p::basic::Scheduler> scheduler)
18  : scheduler_{std::move(scheduler)},
19  log_(log::createLogger("Reputation", "reputation")) {
20  BOOST_ASSERT(scheduler_);
21 
22  tick_handler_ = scheduler_->scheduleWithHandle([&] { tick(); }, 1s);
23  }
24 
26  const ReputationRepository::PeerId &peer_id) const {
27  auto it = reputation_table_.find(peer_id);
28  return it != reputation_table_.end() ? it->second : 0;
29  }
30 
32  const ReputationRepository::PeerId &peer_id, ReputationChange diff) {
33  auto reputation = reputation_table_[peer_id] += diff.value;
34  SL_DEBUG(log_,
35  "Reputation of peer {} was changed by {} points to {} points. "
36  "Reason: `{}'",
37  peer_id,
38  diff.value,
39  reputation,
40  diff.reason);
41  return reputation;
42  }
43 
45  const ReputationRepository::PeerId &peer_id,
46  ReputationChange diff,
47  std::chrono::seconds duration) {
48  auto reputation = reputation_table_[peer_id] += diff.value;
49  SL_DEBUG(log_,
50  "Reputation of peer {} was changed by {} points to {} points "
51  "for {} seconds. Reason: `{}'",
52  peer_id,
53  diff.value,
54  reputation,
55  duration.count(),
56  diff.reason);
57 
58  auto value = static_cast<Reputation>(
59  -static_cast<double>(diff.value) // opposite original
60  * std::pow(0.98, duration.count()) // multiplier considering timeout
61  );
62 
63  if (value != 0) {
64  scheduler_->schedule(
65  [wp = weak_from_this(), peer_id, value, reason = diff.reason] {
66  if (auto self = wp.lock()) {
67  auto reputation = self->reputation_table_[peer_id] += value;
68  SL_DEBUG(self->log_,
69  "Reputation of peer {} was changed by {} points to {} "
70  "points. Reason: reverse of `{}'",
71  peer_id,
72  value,
73  reputation,
74  reason);
75  }
76  },
77  duration);
78  }
79 
80  return reputation;
81  }
82 
84  // For each elapsed second, move the node reputation towards zero.
85  // If we multiply each second the reputation by `k` (where `k` is 0..1), it
86  // takes `ln(0.5) / ln(k)` seconds to reduce the reputation by half. Use
87  // this formula to empirically determine a value of `k` that looks correct.
88  for (auto it = reputation_table_.begin(); it != reputation_table_.end();) {
89  auto cit = it++;
90  auto &peer_id = cit->first;
91  auto &reputation = cit->second;
92 
93  // We use `k = 0.98`, so we divide by `50`. With that value, it takes 34.3
94  // seconds to reduce the reputation by half.
95  auto diff = reputation / 50;
96 
97  if (diff == 0) {
98  diff = reputation < 0 ? -1 : 1;
99  }
100  reputation -= diff;
101 
102  SL_TRACE(
103  log_,
104  "Reputation of peer {} was changed by {} points to {} points by tick",
105  peer_id,
106  -diff,
107  reputation);
108 
109  if (reputation == 0) {
110  reputation_table_.erase(cit);
111  }
112  }
113  std::ignore = tick_handler_.reschedule(1s);
114  }
115 
116 } // namespace kagome::network
std::shared_ptr< libp2p::basic::Scheduler > scheduler_
Reputation reputation(const PeerId &peer_id) const override
Current peer reputation.
Reputation changeForATime(const PeerId &peer_id, ReputationChange diff, std::chrono::seconds duration) override
std::int32_t Reputation
Reputation change(const PeerId &peer_id, ReputationChange diff) override
std::unordered_map< PeerId, Reputation > reputation_table_
Logger createLogger(const std::string &tag)
Definition: logger.cpp:112