rippled
InboundTransactions.cpp
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 #include <ripple/app/ledger/InboundLedgers.h>
21 #include <ripple/app/ledger/InboundTransactions.h>
22 #include <ripple/app/ledger/impl/TransactionAcquire.h>
23 #include <ripple/app/main/Application.h>
24 #include <ripple/app/misc/NetworkOPs.h>
25 #include <ripple/basics/Log.h>
26 #include <ripple/core/JobQueue.h>
27 #include <ripple/protocol/RippleLedgerHash.h>
28 #include <ripple/resource/Fees.h>
29 #include <memory>
30 #include <mutex>
31 
32 namespace ripple {
33 
34 enum {
35  // Ideal number of peers to start with
37 
38  // How many rounds to keep a set
40 };
41 
43 {
44  // A transaction set we generated, acquired, or are acquiring
45 public:
49 
51  : mSeq(seq), mSet(set)
52  {
53  ;
54  }
56  {
57  ;
58  }
59 };
60 
62 {
63 public:
65  Application& app,
66  beast::insight::Collector::ptr const& collector,
67  std::function<void(std::shared_ptr<SHAMap> const&, bool)> gotSet,
68  std::unique_ptr<PeerSetBuilder> peerSetBuilder)
69  : app_(app)
70  , m_seq(0)
71  , m_zeroSet(m_map[uint256()])
72  , m_gotSet(std::move(gotSet))
73  , m_peerSetBuilder(std::move(peerSetBuilder))
74  , j_(app_.journal("InboundTransactions"))
75  {
76  m_zeroSet.mSet = std::make_shared<SHAMap>(
78  m_zeroSet.mSet->setUnbacked();
79  }
80 
82  getAcquire(uint256 const& hash)
83  {
84  {
86 
87  auto it = m_map.find(hash);
88 
89  if (it != m_map.end())
90  return it->second.mAcquire;
91  }
92  return {};
93  }
94 
96  getSet(uint256 const& hash, bool acquire) override
97  {
99 
100  {
102 
103  if (auto it = m_map.find(hash); it != m_map.end())
104  {
105  if (acquire)
106  {
107  it->second.mSeq = m_seq;
108  if (it->second.mAcquire)
109  {
110  it->second.mAcquire->stillNeed();
111  }
112  }
113  return it->second.mSet;
114  }
115 
116  if (!acquire || stopping_)
117  return std::shared_ptr<SHAMap>();
118 
119  ta = std::make_shared<TransactionAcquire>(
120  app_, hash, m_peerSetBuilder->build());
121 
122  auto& obj = m_map[hash];
123  obj.mAcquire = ta;
124  obj.mSeq = m_seq;
125  }
126 
127  ta->init(startPeers);
128 
129  return {};
130  }
131 
134  void
136  LedgerHash const& hash,
138  std::shared_ptr<protocol::TMLedgerData> packet_ptr) override
139  {
140  protocol::TMLedgerData& packet = *packet_ptr;
141 
142  JLOG(j_.trace()) << "Got data (" << packet.nodes().size()
143  << ") for acquiring ledger: " << hash;
144 
146 
147  if (ta == nullptr)
148  {
149  peer->charge(Resource::feeUnwantedData);
150  return;
151  }
152 
154  data.reserve(packet.nodes().size());
155 
156  for (auto const& node : packet.nodes())
157  {
158  if (!node.has_nodeid() || !node.has_nodedata())
159  {
160  peer->charge(Resource::feeInvalidRequest);
161  return;
162  }
163 
164  auto const id = deserializeSHAMapNodeID(node.nodeid());
165 
166  if (!id)
167  {
168  peer->charge(Resource::feeBadData);
169  return;
170  }
171 
172  data.emplace_back(std::make_pair(*id, makeSlice(node.nodedata())));
173  }
174 
175  if (!ta->takeNodes(data, peer).isUseful())
176  peer->charge(Resource::feeUnwantedData);
177  }
178 
179  void
181  uint256 const& hash,
183  bool fromAcquire) override
184  {
185  bool isNew = true;
186 
187  {
189 
190  auto& inboundSet = m_map[hash];
191 
192  if (inboundSet.mSeq < m_seq)
193  inboundSet.mSeq = m_seq;
194 
195  if (inboundSet.mSet)
196  isNew = false;
197  else
198  inboundSet.mSet = set;
199 
200  inboundSet.mAcquire.reset();
201  }
202 
203  if (isNew)
204  m_gotSet(set, fromAcquire);
205  }
206 
207  void
208  newRound(std::uint32_t seq) override
209  {
210  std::lock_guard lock(mLock);
211 
212  // Protect zero set from expiration
213  m_zeroSet.mSeq = seq;
214 
215  if (m_seq != seq)
216  {
217  m_seq = seq;
218 
219  auto it = m_map.begin();
220 
221  std::uint32_t const minSeq =
222  (seq < setKeepRounds) ? 0 : (seq - setKeepRounds);
223  std::uint32_t maxSeq = seq + setKeepRounds;
224 
225  while (it != m_map.end())
226  {
227  if (it->second.mSeq < minSeq || it->second.mSeq > maxSeq)
228  it = m_map.erase(it);
229  else
230  ++it;
231  }
232  }
233  }
234 
235  void
236  stop() override
237  {
238  std::lock_guard lock(mLock);
239  stopping_ = true;
240  m_map.clear();
241  }
242 
243 private:
245 
247 
249 
250  bool stopping_{false};
253 
254  // The empty transaction set whose hash is zero
256 
258 
260 
262 };
263 
264 //------------------------------------------------------------------------------
265 
267 
270  Application& app,
271  beast::insight::Collector::ptr const& collector,
272  std::function<void(std::shared_ptr<SHAMap> const&, bool)> gotSet)
273 {
274  return std::make_unique<InboundTransactionsImp>(
275  app, collector, std::move(gotSet), make_PeerSetBuilder(app));
276 }
277 
278 } // namespace ripple
ripple::Resource::feeInvalidRequest
const Charge feeInvalidRequest
Schedule of fees charged for imposing load on the server.
ripple::Application
Definition: Application.h:115
ripple::Application::getNodeFamily
virtual Family & getNodeFamily()=0
ripple::InboundTransactionSet::InboundTransactionSet
InboundTransactionSet(std::uint32_t seq, std::shared_ptr< SHAMap > const &set)
Definition: InboundTransactions.cpp:50
ripple::InboundTransactionsImp::stopping_
bool stopping_
Definition: InboundTransactions.cpp:250
ripple::makeSlice
std::enable_if_t< std::is_same< T, char >::value||std::is_same< T, unsigned char >::value, Slice > makeSlice(std::array< T, N > const &a)
Definition: Slice.h:241
std::shared_ptr< TransactionAcquire >
ripple::InboundTransactionsImp::app_
Application & app_
Definition: InboundTransactions.cpp:246
beast::Journal::trace
Stream trace() const
Severity stream access functions.
Definition: Journal.h:309
ripple::deserializeSHAMapNodeID
std::optional< SHAMapNodeID > deserializeSHAMapNodeID(void const *data, std::size_t size)
Return an object representing a serialized SHAMap Node ID.
Definition: SHAMapNodeID.cpp:101
ripple::SHAMapType::TRANSACTION
@ TRANSACTION
ripple::InboundTransactionsImp::InboundTransactionsImp
InboundTransactionsImp(Application &app, beast::insight::Collector::ptr const &collector, std::function< void(std::shared_ptr< SHAMap > const &, bool)> gotSet, std::unique_ptr< PeerSetBuilder > peerSetBuilder)
Definition: InboundTransactions.cpp:64
ripple::InboundTransactionsImp::stop
void stop() override
Definition: InboundTransactions.cpp:236
std::vector
STL class.
std::unordered_map::find
T find(T... args)
ripple::InboundTransactionsImp::giveSet
void giveSet(uint256 const &hash, std::shared_ptr< SHAMap > const &set, bool fromAcquire) override
Add a transaction set.
Definition: InboundTransactions.cpp:180
std::recursive_mutex
STL class.
std::lock_guard
STL class.
ripple::InboundTransactionsImp::mLock
std::recursive_mutex mLock
Definition: InboundTransactions.cpp:248
std::function
ripple::make_InboundTransactions
std::unique_ptr< InboundTransactions > make_InboundTransactions(Application &app, beast::insight::Collector::ptr const &collector, std::function< void(std::shared_ptr< SHAMap > const &, bool)> gotSet)
Definition: InboundTransactions.cpp:269
ripple::InboundTransactionsImp
Definition: InboundTransactions.cpp:61
ripple::startPeers
@ startPeers
Definition: InboundTransactions.cpp:36
std::unordered_map::clear
T clear(T... args)
ripple::uint256
base_uint< 256 > uint256
Definition: base_uint.h:550
ripple::InboundTransactionSet::mSeq
std::uint32_t mSeq
Definition: InboundTransactions.cpp:46
ripple::base_uint< 256 >
ripple::InboundTransactionSet::mSet
std::shared_ptr< SHAMap > mSet
Definition: InboundTransactions.cpp:48
ripple::InboundTransactionsImp::m_zeroSet
InboundTransactionSet & m_zeroSet
Definition: InboundTransactions.cpp:255
ripple::InboundTransactionSet
Definition: InboundTransactions.cpp:42
ripple::InboundTransactionsImp::m_peerSetBuilder
std::unique_ptr< PeerSetBuilder > m_peerSetBuilder
Definition: InboundTransactions.cpp:259
ripple::Resource::feeBadData
const Charge feeBadData
ripple::InboundTransactionsImp::m_gotSet
std::function< void(std::shared_ptr< SHAMap > const &, bool)> m_gotSet
Definition: InboundTransactions.cpp:257
ripple::InboundTransactionsImp::getAcquire
TransactionAcquire::pointer getAcquire(uint256 const &hash)
Definition: InboundTransactions.cpp:82
ripple::InboundTransactionsImp::m_map
MapType m_map
Definition: InboundTransactions.cpp:251
ripple::setKeepRounds
@ setKeepRounds
Definition: InboundTransactions.cpp:39
ripple::Resource::feeUnwantedData
const Charge feeUnwantedData
ripple::set
bool set(T &target, std::string const &name, Section const &section)
Set a value from a configuration Section If the named value is not found or doesn't parse as a T,...
Definition: BasicConfig.h:313
std::unordered_map::erase
T erase(T... args)
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
std::uint32_t
memory
ripple::InboundTransactionSet::InboundTransactionSet
InboundTransactionSet()
Definition: InboundTransactions.cpp:55
ripple::InboundTransactionsImp::getSet
std::shared_ptr< SHAMap > getSet(uint256 const &hash, bool acquire) override
Find and return a transaction set, or nullptr if it is missing.
Definition: InboundTransactions.cpp:96
ripple::InboundTransactionsImp::m_seq
std::uint32_t m_seq
Definition: InboundTransactions.cpp:252
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::ShardState::acquire
@ acquire
ripple::make_PeerSetBuilder
std::unique_ptr< PeerSetBuilder > make_PeerSetBuilder(Application &app)
Definition: PeerSet.cpp:144
std::unordered_map::begin
T begin(T... args)
std
STL namespace.
ripple::InboundTransactionsImp::gotData
void gotData(LedgerHash const &hash, std::shared_ptr< Peer > peer, std::shared_ptr< protocol::TMLedgerData > packet_ptr) override
We received a TMLedgerData from a peer.
Definition: InboundTransactions.cpp:135
ripple::InboundTransactions::~InboundTransactions
virtual ~InboundTransactions()=0
ripple::InboundTransactionsImp::j_
beast::Journal j_
Definition: InboundTransactions.cpp:261
ripple::InboundTransactionsImp::newRound
void newRound(std::uint32_t seq) override
Informs the container if a new consensus round.
Definition: InboundTransactions.cpp:208
mutex
std::make_pair
T make_pair(T... args)
std::unordered_map::end
T end(T... args)
ripple::InboundTransactionSet::mAcquire
TransactionAcquire::pointer mAcquire
Definition: InboundTransactions.cpp:47
std::unique_ptr
STL class.
std::unordered_map
STL class.
ripple::InboundTransactions
Manages the acquisition and lifetime of transaction sets.
Definition: InboundTransactions.h:35