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 
67  Application& app,
68  Stoppable& parent,
69  beast::insight::Collector::ptr const& collector,
70  std::function<void(std::shared_ptr<SHAMap> const&, bool)> gotSet)
71  : Stoppable("InboundTransactions", parent)
72  , app_(app)
73  , m_seq(0)
74  , m_zeroSet(m_map[uint256()])
75  , m_gotSet(std::move(gotSet))
76  {
77  m_zeroSet.mSet = std::make_shared<SHAMap>(
79  m_zeroSet.mSet->setUnbacked();
80  }
81 
83  getAcquire(uint256 const& hash)
84  {
85  {
87 
88  auto it = m_map.find(hash);
89 
90  if (it != m_map.end())
91  return it->second.mAcquire;
92  }
93  return {};
94  }
95 
97  getSet(uint256 const& hash, bool acquire) override
98  {
100 
101  {
103 
104  auto it = m_map.find(hash);
105 
106  if (it != m_map.end())
107  {
108  if (acquire)
109  {
110  it->second.mSeq = m_seq;
111  if (it->second.mAcquire)
112  {
113  it->second.mAcquire->stillNeed();
114  }
115  }
116  return it->second.mSet;
117  }
118 
119  if (!acquire || isStopping())
120  return std::shared_ptr<SHAMap>();
121 
122  ta = std::make_shared<TransactionAcquire>(app_, hash);
123 
124  auto& obj = m_map[hash];
125  obj.mAcquire = ta;
126  obj.mSeq = m_seq;
127  }
128 
129  ta->init(startPeers);
130 
131  return {};
132  }
133 
136  void
138  LedgerHash const& hash,
140  std::shared_ptr<protocol::TMLedgerData> packet_ptr) override
141  {
142  protocol::TMLedgerData& packet = *packet_ptr;
143 
144  JLOG(app_.journal("InboundLedger").trace())
145  << "Got data (" << packet.nodes().size()
146  << ") "
147  "for acquiring ledger: "
148  << hash;
149 
151 
152  if (ta == nullptr)
153  {
154  peer->charge(Resource::feeUnwantedData);
155  return;
156  }
157 
158  std::list<SHAMapNodeID> nodeIDs;
159  std::list<Blob> nodeData;
160  for (auto const& node : packet.nodes())
161  {
162  if (!node.has_nodeid() || !node.has_nodedata())
163  {
164  peer->charge(Resource::feeInvalidRequest);
165  return;
166  }
167 
168  auto const id = deserializeSHAMapNodeID(node.nodeid());
169 
170  if (!id)
171  {
172  peer->charge(Resource::feeBadData);
173  return;
174  }
175 
176  nodeIDs.emplace_back(*id);
177  nodeData.emplace_back(
178  node.nodedata().begin(), node.nodedata().end());
179  }
180 
181  if (!ta->takeNodes(nodeIDs, nodeData, peer).isUseful())
182  peer->charge(Resource::feeUnwantedData);
183  }
184 
185  void
187  uint256 const& hash,
189  bool fromAcquire) override
190  {
191  bool isNew = true;
192 
193  {
195 
196  auto& inboundSet = m_map[hash];
197 
198  if (inboundSet.mSeq < m_seq)
199  inboundSet.mSeq = m_seq;
200 
201  if (inboundSet.mSet)
202  isNew = false;
203  else
204  inboundSet.mSet = set;
205 
206  inboundSet.mAcquire.reset();
207  }
208 
209  if (isNew)
210  m_gotSet(set, fromAcquire);
211  }
212 
213  void
214  newRound(std::uint32_t seq) override
215  {
216  std::lock_guard lock(mLock);
217 
218  // Protect zero set from expiration
219  m_zeroSet.mSeq = seq;
220 
221  if (m_seq != seq)
222  {
223  m_seq = seq;
224 
225  auto it = m_map.begin();
226 
227  std::uint32_t const minSeq =
228  (seq < setKeepRounds) ? 0 : (seq - setKeepRounds);
229  std::uint32_t maxSeq = seq + setKeepRounds;
230 
231  while (it != m_map.end())
232  {
233  if (it->second.mSeq < minSeq || it->second.mSeq > maxSeq)
234  it = m_map.erase(it);
235  else
236  ++it;
237  }
238  }
239  }
240 
241  void
242  onStop() override
243  {
244  std::lock_guard lock(mLock);
245 
246  m_map.clear();
247 
248  stopped();
249  }
250 
251 private:
253 
255 
258 
259  // The empty transaction set whose hash is zero
261 
263 };
264 
265 //------------------------------------------------------------------------------
266 
268 
271  Application& app,
272  Stoppable& parent,
273  beast::insight::Collector::ptr const& collector,
274  std::function<void(std::shared_ptr<SHAMap> const&, bool)> gotSet)
275 {
276  return std::make_unique<InboundTransactionsImp>(
277  app, parent, collector, std::move(gotSet));
278 }
279 
280 } // namespace ripple
ripple::Resource::feeInvalidRequest
const Charge feeInvalidRequest
Schedule of fees charged for imposing load on the server.
ripple::Application
Definition: Application.h:97
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
std::shared_ptr< TransactionAcquire >
ripple::Stoppable::stopped
void stopped()
Called by derived classes to indicate that the stoppable has stopped.
Definition: Stoppable.cpp:72
std::list
STL class.
ripple::InboundTransactionsImp::app_
Application & app_
Definition: InboundTransactions.cpp:64
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
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:186
std::recursive_mutex
STL class.
std::lock_guard
STL class.
ripple::InboundTransactionsImp::mLock
std::recursive_mutex mLock
Definition: InboundTransactions.cpp:254
std::function
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:457
ripple::InboundTransactionSet::mSeq
std::uint32_t mSeq
Definition: InboundTransactions.cpp:46
ripple::base_uint< 256 >
ripple::InboundTransactionsImp::onStop
void onStop() override
Override called when the stop notification is issued.
Definition: InboundTransactions.cpp:242
ripple::Stoppable
Provides an interface for starting and stopping.
Definition: Stoppable.h:201
ripple::InboundTransactionSet::mSet
std::shared_ptr< SHAMap > mSet
Definition: InboundTransactions.cpp:48
ripple::InboundTransactionsImp::m_zeroSet
InboundTransactionSet & m_zeroSet
Definition: InboundTransactions.cpp:260
ripple::InboundTransactionSet
Definition: InboundTransactions.cpp:42
ripple::Resource::feeBadData
const Charge feeBadData
ripple::InboundTransactionsImp::m_gotSet
std::function< void(std::shared_ptr< SHAMap > const &, bool)> m_gotSet
Definition: InboundTransactions.cpp:262
ripple::InboundTransactionsImp::getAcquire
TransactionAcquire::pointer getAcquire(uint256 const &hash)
Definition: InboundTransactions.cpp:83
ripple::InboundTransactionsImp::m_map
MapType m_map
Definition: InboundTransactions.cpp:256
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:276
std::unordered_map::erase
T erase(T... args)
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:97
ripple::InboundTransactionsImp::m_seq
std::uint32_t m_seq
Definition: InboundTransactions.cpp:257
std::list::emplace_back
T emplace_back(T... args)
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::Application::journal
virtual beast::Journal journal(std::string const &name)=0
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:137
ripple::InboundTransactions::~InboundTransactions
virtual ~InboundTransactions()=0
ripple::InboundTransactionsImp::newRound
void newRound(std::uint32_t seq) override
Informs the container if a new consensus round.
Definition: InboundTransactions.cpp:214
mutex
std::unordered_map::end
T end(T... args)
ripple::InboundTransactionSet::mAcquire
TransactionAcquire::pointer mAcquire
Definition: InboundTransactions.cpp:47
ripple::InboundTransactionsImp::InboundTransactionsImp
InboundTransactionsImp(Application &app, Stoppable &parent, beast::insight::Collector::ptr const &collector, std::function< void(std::shared_ptr< SHAMap > const &, bool)> gotSet)
Definition: InboundTransactions.cpp:66
ripple::make_InboundTransactions
std::unique_ptr< InboundTransactions > make_InboundTransactions(Application &app, Stoppable &parent, beast::insight::Collector::ptr const &collector, std::function< void(std::shared_ptr< SHAMap > const &, bool)> gotSet)
Definition: InboundTransactions.cpp:270
std::unique_ptr
STL class.
std::unordered_map
STL class.
ripple::InboundTransactions
Manages the acquisition and lifetime of transaction sets.
Definition: InboundTransactions.h:36
ripple::Stoppable::isStopping
bool isStopping() const
Returns true if the stoppable should stop.
Definition: Stoppable.cpp:54