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  clock_type& clock,
69  Stoppable& parent,
70  beast::insight::Collector::ptr const& collector,
71  std::function<void(std::shared_ptr<SHAMap> const&, bool)> gotSet)
72  : Stoppable("InboundTransactions", parent)
73  , app_(app)
74  , m_clock(clock)
75  , m_seq(0)
76  , m_zeroSet(m_map[uint256()])
77  , m_gotSet(std::move(gotSet))
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>(app_, hash, m_clock);
125 
126  auto& obj = m_map[hash];
127  obj.mAcquire = ta;
128  obj.mSeq = m_seq;
129  }
130 
131  ta->init(startPeers);
132 
133  return {};
134  }
135 
138  void
140  LedgerHash const& hash,
142  std::shared_ptr<protocol::TMLedgerData> packet_ptr) override
143  {
144  protocol::TMLedgerData& packet = *packet_ptr;
145 
146  JLOG(app_.journal("InboundLedger").trace())
147  << "Got data (" << packet.nodes().size()
148  << ") "
149  "for acquiring ledger: "
150  << hash;
151 
153 
154  if (ta == nullptr)
155  {
156  peer->charge(Resource::feeUnwantedData);
157  return;
158  }
159 
160  std::list<SHAMapNodeID> nodeIDs;
161  std::list<Blob> nodeData;
162  for (auto const& node : packet.nodes())
163  {
164  if (!node.has_nodeid() || !node.has_nodedata() ||
165  (node.nodeid().size() != 33))
166  {
167  peer->charge(Resource::feeInvalidRequest);
168  return;
169  }
170 
171  nodeIDs.emplace_back(
172  node.nodeid().data(), static_cast<int>(node.nodeid().size()));
173  nodeData.emplace_back(
174  node.nodedata().begin(), node.nodedata().end());
175  }
176 
177  if (!ta->takeNodes(nodeIDs, nodeData, peer).isUseful())
178  peer->charge(Resource::feeUnwantedData);
179  }
180 
181  void
183  uint256 const& hash,
185  bool fromAcquire) override
186  {
187  bool isNew = true;
188 
189  {
191 
192  auto& inboundSet = m_map[hash];
193 
194  if (inboundSet.mSeq < m_seq)
195  inboundSet.mSeq = m_seq;
196 
197  if (inboundSet.mSet)
198  isNew = false;
199  else
200  inboundSet.mSet = set;
201 
202  inboundSet.mAcquire.reset();
203  }
204 
205  if (isNew)
206  m_gotSet(set, fromAcquire);
207  }
208 
210  getInfo() override
211  {
213 
214  Json::Value& sets = (ret["sets"] = Json::arrayValue);
215 
216  {
218 
219  ret["seq"] = m_seq;
220 
221  for (auto const& it : m_map)
222  {
223  Json::Value& set = sets[to_string(it.first)];
224  set["seq"] = it.second.mSeq;
225  if (it.second.mSet)
226  set["state"] = "complete";
227  else if (it.second.mAcquire)
228  set["state"] = "acquiring";
229  else
230  set["state"] = "dead";
231  }
232  }
233 
234  return ret;
235  }
236 
237  void
238  newRound(std::uint32_t seq) override
239  {
240  std::lock_guard lock(mLock);
241 
242  // Protect zero set from expiration
243  m_zeroSet.mSeq = seq;
244 
245  if (m_seq != seq)
246  {
247  m_seq = seq;
248 
249  auto it = m_map.begin();
250 
251  std::uint32_t const minSeq =
252  (seq < setKeepRounds) ? 0 : (seq - setKeepRounds);
253  std::uint32_t maxSeq = seq + setKeepRounds;
254 
255  while (it != m_map.end())
256  {
257  if (it->second.mSeq < minSeq || it->second.mSeq > maxSeq)
258  it = m_map.erase(it);
259  else
260  ++it;
261  }
262  }
263  }
264 
265  void
266  onStop() override
267  {
268  std::lock_guard lock(mLock);
269 
270  m_map.clear();
271 
272  stopped();
273  }
274 
275 private:
277 
279 
281 
284 
285  // The empty transaction set whose hash is zero
287 
289 };
290 
291 //------------------------------------------------------------------------------
292 
294 
297  Application& app,
299  Stoppable& parent,
300  beast::insight::Collector::ptr const& collector,
301  std::function<void(std::shared_ptr<SHAMap> const&, bool)> gotSet)
302 {
303  return std::make_unique<InboundTransactionsImp>(
304  app, clock, parent, collector, std::move(gotSet));
305 }
306 
307 } // namespace ripple
ripple::Resource::feeInvalidRequest
const Charge feeInvalidRequest
Schedule of fees charged for imposing load on the server.
ripple::Application
Definition: Application.h:94
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
Json::arrayValue
@ arrayValue
array value (ordered list)
Definition: json_value.h:42
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
Gives set to the container.
Definition: InboundTransactions.cpp:182
std::recursive_mutex
STL class.
std::lock_guard
STL class.
ripple::InboundTransactionsImp::mLock
std::recursive_mutex mLock
Definition: InboundTransactions.cpp:280
std::function
ripple::to_string
std::string to_string(ListDisposition disposition)
Definition: ValidatorList.cpp:41
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
Definition: InboundTransactions.cpp:266
ripple::InboundTransactions::clock_type
beast::abstract_clock< std::chrono::steady_clock > clock_type
Definition: InboundTransactions.h:39
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:286
ripple::InboundTransactionSet
Definition: InboundTransactions.cpp:42
ripple::Application::family
virtual Family & family()=0
Json::objectValue
@ objectValue
object value (collection of name/value pairs).
Definition: json_value.h:43
ripple::InboundTransactionsImp::m_gotSet
std::function< void(std::shared_ptr< SHAMap > const &, bool)> m_gotSet
Definition: InboundTransactions.cpp:288
ripple::InboundTransactionsImp::getAcquire
TransactionAcquire::pointer getAcquire(uint256 const &hash)
Definition: InboundTransactions.cpp:85
ripple::InboundTransactionsImp::m_map
MapType m_map
Definition: InboundTransactions.cpp:282
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
ripple::InboundTransactionsImp::m_clock
clock_type & m_clock
Definition: InboundTransactions.cpp:276
ripple::make_InboundTransactions
std::unique_ptr< InboundTransactions > make_InboundTransactions(Application &app, InboundLedgers::clock_type &clock, Stoppable &parent, beast::insight::Collector::ptr const &collector, std::function< void(std::shared_ptr< SHAMap > const &, bool)> gotSet)
Definition: InboundTransactions.cpp:296
std::unordered_map::erase
T erase(T... args)
std::uint32_t
beast::abstract_clock< std::chrono::steady_clock >
memory
ripple::InboundTransactionSet::InboundTransactionSet
InboundTransactionSet()
Definition: InboundTransactions.cpp:55
ripple::InboundTransactionsImp::getSet
std::shared_ptr< SHAMap > getSet(uint256 const &hash, bool acquire) override
Retrieves a transaction set by hash.
Definition: InboundTransactions.cpp:99
ripple::InboundTransactionsImp::m_seq
std::uint32_t m_seq
Definition: InboundTransactions.cpp:283
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)
ripple::InboundTransactionsImp::InboundTransactionsImp
InboundTransactionsImp(Application &app, clock_type &clock, Stoppable &parent, beast::insight::Collector::ptr const &collector, std::function< void(std::shared_ptr< SHAMap > const &, bool)> gotSet)
Definition: InboundTransactions.cpp:66
std
STL namespace.
ripple::InboundTransactionsImp::getInfo
Json::Value getInfo() override
Definition: InboundTransactions.cpp:210
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:139
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:238
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.
Json::Value
Represents a JSON value.
Definition: json_value.h:145
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