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  (node.nodeid().size() != 33))
164  {
165  peer->charge(Resource::feeInvalidRequest);
166  return;
167  }
168 
169  nodeIDs.emplace_back(
170  node.nodeid().data(), static_cast<int>(node.nodeid().size()));
171  nodeData.emplace_back(
172  node.nodedata().begin(), node.nodedata().end());
173  }
174 
175  if (!ta->takeNodes(nodeIDs, nodeData, 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  onStop() override
237  {
238  std::lock_guard lock(mLock);
239 
240  m_map.clear();
241 
242  stopped();
243  }
244 
245 private:
247 
249 
252 
253  // The empty transaction set whose hash is zero
255 
257 };
258 
259 //------------------------------------------------------------------------------
260 
262 
265  Application& app,
266  Stoppable& parent,
267  beast::insight::Collector::ptr const& collector,
268  std::function<void(std::shared_ptr<SHAMap> const&, bool)> gotSet)
269 {
270  return std::make_unique<InboundTransactionsImp>(
271  app, parent, collector, std::move(gotSet));
272 }
273 
274 } // 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::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: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::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:493
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:236
ripple::Stoppable
Provides an interface for starting and stopping.
Definition: Stoppable.h:200
ripple::InboundTransactionSet::mSet
std::shared_ptr< SHAMap > mSet
Definition: InboundTransactions.cpp:48
ripple::InboundTransactionsImp::m_zeroSet
InboundTransactionSet & m_zeroSet
Definition: InboundTransactions.cpp:254
ripple::InboundTransactionSet
Definition: InboundTransactions.cpp:42
ripple::InboundTransactionsImp::m_gotSet
std::function< void(std::shared_ptr< SHAMap > const &, bool)> m_gotSet
Definition: InboundTransactions.cpp:256
ripple::InboundTransactionsImp::getAcquire
TransactionAcquire::pointer getAcquire(uint256 const &hash)
Definition: InboundTransactions.cpp:83
ripple::InboundTransactionsImp::m_map
MapType m_map
Definition: InboundTransactions.cpp:250
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:251
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:208
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:264
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