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