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  std::unique_ptr<PeerSetBuilder> peerSetBuilder)
72  : Stoppable("InboundTransactions", parent)
73  , app_(app)
74  , m_seq(0)
75  , m_zeroSet(m_map[uint256()])
76  , m_gotSet(std::move(gotSet))
77  , m_peerSetBuilder(std::move(peerSetBuilder))
78  {
79  m_zeroSet.mSet = std::make_shared<SHAMap>(
81  m_zeroSet.mSet->setUnbacked();
82  }
83 
85  getAcquire(uint256 const& hash)
86  {
87  {
89 
90  auto it = m_map.find(hash);
91 
92  if (it != m_map.end())
93  return it->second.mAcquire;
94  }
95  return {};
96  }
97 
99  getSet(uint256 const& hash, bool acquire) override
100  {
102 
103  {
105 
106  auto it = m_map.find(hash);
107 
108  if (it != m_map.end())
109  {
110  if (acquire)
111  {
112  it->second.mSeq = m_seq;
113  if (it->second.mAcquire)
114  {
115  it->second.mAcquire->stillNeed();
116  }
117  }
118  return it->second.mSet;
119  }
120 
121  if (!acquire || isStopping())
122  return std::shared_ptr<SHAMap>();
123 
124  ta = std::make_shared<TransactionAcquire>(
125  app_, hash, m_peerSetBuilder->build());
126 
127  auto& obj = m_map[hash];
128  obj.mAcquire = ta;
129  obj.mSeq = m_seq;
130  }
131 
132  ta->init(startPeers);
133 
134  return {};
135  }
136 
139  void
141  LedgerHash const& hash,
143  std::shared_ptr<protocol::TMLedgerData> packet_ptr) override
144  {
145  protocol::TMLedgerData& packet = *packet_ptr;
146 
147  JLOG(app_.journal("InboundLedger").trace())
148  << "Got data (" << packet.nodes().size()
149  << ") "
150  "for acquiring ledger: "
151  << hash;
152 
154 
155  if (ta == nullptr)
156  {
157  peer->charge(Resource::feeUnwantedData);
158  return;
159  }
160 
161  std::list<SHAMapNodeID> nodeIDs;
162  std::list<Blob> nodeData;
163  for (auto const& node : packet.nodes())
164  {
165  if (!node.has_nodeid() || !node.has_nodedata())
166  {
167  peer->charge(Resource::feeInvalidRequest);
168  return;
169  }
170 
171  auto const id = deserializeSHAMapNodeID(node.nodeid());
172 
173  if (!id)
174  {
175  peer->charge(Resource::feeBadData);
176  return;
177  }
178 
179  nodeIDs.emplace_back(*id);
180  nodeData.emplace_back(
181  node.nodedata().begin(), node.nodedata().end());
182  }
183 
184  if (!ta->takeNodes(nodeIDs, nodeData, peer).isUseful())
185  peer->charge(Resource::feeUnwantedData);
186  }
187 
188  void
190  uint256 const& hash,
192  bool fromAcquire) override
193  {
194  bool isNew = true;
195 
196  {
198 
199  auto& inboundSet = m_map[hash];
200 
201  if (inboundSet.mSeq < m_seq)
202  inboundSet.mSeq = m_seq;
203 
204  if (inboundSet.mSet)
205  isNew = false;
206  else
207  inboundSet.mSet = set;
208 
209  inboundSet.mAcquire.reset();
210  }
211 
212  if (isNew)
213  m_gotSet(set, fromAcquire);
214  }
215 
216  void
217  newRound(std::uint32_t seq) override
218  {
219  std::lock_guard lock(mLock);
220 
221  // Protect zero set from expiration
222  m_zeroSet.mSeq = seq;
223 
224  if (m_seq != seq)
225  {
226  m_seq = seq;
227 
228  auto it = m_map.begin();
229 
230  std::uint32_t const minSeq =
231  (seq < setKeepRounds) ? 0 : (seq - setKeepRounds);
232  std::uint32_t maxSeq = seq + setKeepRounds;
233 
234  while (it != m_map.end())
235  {
236  if (it->second.mSeq < minSeq || it->second.mSeq > maxSeq)
237  it = m_map.erase(it);
238  else
239  ++it;
240  }
241  }
242  }
243 
244  void
245  onStop() override
246  {
247  std::lock_guard lock(mLock);
248 
249  m_map.clear();
250 
251  stopped();
252  }
253 
254 private:
256 
258 
261 
262  // The empty transaction set whose hash is zero
264 
266 
268 };
269 
270 //------------------------------------------------------------------------------
271 
273 
276  Application& app,
277  Stoppable& parent,
278  beast::insight::Collector::ptr const& collector,
279  std::function<void(std::shared_ptr<SHAMap> const&, bool)> gotSet)
280 {
281  return std::make_unique<InboundTransactionsImp>(
282  app, parent, collector, std::move(gotSet), make_PeerSetBuilder(app));
283 }
284 
285 } // namespace ripple
ripple::Resource::feeInvalidRequest
const Charge feeInvalidRequest
Schedule of fees charged for imposing load on the server.
ripple::Application
Definition: Application.h:102
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:189
std::recursive_mutex
STL class.
std::lock_guard
STL class.
ripple::InboundTransactionsImp::mLock
std::recursive_mutex mLock
Definition: InboundTransactions.cpp:257
std::function
ripple::InboundTransactionsImp
Definition: InboundTransactions.cpp:61
ripple::startPeers
@ startPeers
Definition: InboundTransactions.cpp:36
std::unordered_map::clear
T clear(T... args)
ripple::InboundTransactionsImp::InboundTransactionsImp
InboundTransactionsImp(Application &app, Stoppable &parent, beast::insight::Collector::ptr const &collector, std::function< void(std::shared_ptr< SHAMap > const &, bool)> gotSet, std::unique_ptr< PeerSetBuilder > peerSetBuilder)
Definition: InboundTransactions.cpp:66
ripple::uint256
base_uint< 256 > uint256
Definition: base_uint.h:526
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:245
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:263
ripple::InboundTransactionSet
Definition: InboundTransactions.cpp:42
ripple::InboundTransactionsImp::m_peerSetBuilder
std::unique_ptr< PeerSetBuilder > m_peerSetBuilder
Definition: InboundTransactions.cpp:267
ripple::Resource::feeBadData
const Charge feeBadData
ripple::InboundTransactionsImp::m_gotSet
std::function< void(std::shared_ptr< SHAMap > const &, bool)> m_gotSet
Definition: InboundTransactions.cpp:265
ripple::InboundTransactionsImp::getAcquire
TransactionAcquire::pointer getAcquire(uint256 const &hash)
Definition: InboundTransactions.cpp:85
ripple::InboundTransactionsImp::m_map
MapType m_map
Definition: InboundTransactions.cpp:259
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:99
ripple::InboundTransactionsImp::m_seq
std::uint32_t m_seq
Definition: InboundTransactions.cpp:260
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
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:140
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:217
mutex
std::unordered_map::end
T end(T... args)
ripple::InboundTransactionSet::mAcquire
TransactionAcquire::pointer mAcquire
Definition: InboundTransactions.cpp:47
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:275
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