rippled
Loading...
Searching...
No Matches
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 <xrpld/app/ledger/InboundLedgers.h>
21#include <xrpld/app/ledger/InboundTransactions.h>
22#include <xrpld/app/ledger/detail/TransactionAcquire.h>
23#include <xrpld/app/main/Application.h>
24#include <xrpld/app/misc/NetworkOPs.h>
25#include <xrpld/core/JobQueue.h>
26
27#include <xrpl/basics/Log.h>
28#include <xrpl/protocol/RippleLedgerHash.h>
29#include <xrpl/resource/Fees.h>
30
31#include <memory>
32#include <mutex>
33
34namespace ripple {
35
36enum {
37 // Ideal number of peers to start with
39
40 // How many rounds to keep a set
42};
43
45{
46 // A transaction set we generated, acquired, or are acquiring
47public:
51
53 : mSeq(seq), mSet(set)
54 {
55 ;
56 }
58 {
59 ;
60 }
61};
62
64{
65public:
67 Application& app,
68 beast::insight::Collector::ptr const& collector,
69 std::function<void(std::shared_ptr<SHAMap> const&, bool)> gotSet,
71 : app_(app)
72 , m_seq(0)
74 , m_gotSet(std::move(gotSet))
75 , m_peerSetBuilder(std::move(peerSetBuilder))
76 , j_(app_.journal("InboundTransactions"))
77 {
80 m_zeroSet.mSet->setUnbacked();
81 }
82
84 getAcquire(uint256 const& hash)
85 {
86 {
88
89 auto it = m_map.find(hash);
90
91 if (it != m_map.end())
92 return it->second.mAcquire;
93 }
94 return {};
95 }
96
98 getSet(uint256 const& hash, bool acquire) override
99 {
101
102 {
104
105 if (auto it = m_map.find(hash); it != m_map.end())
106 {
107 if (acquire)
108 {
109 it->second.mSeq = m_seq;
110 if (it->second.mAcquire)
111 {
112 it->second.mAcquire->stillNeed();
113 }
114 }
115 return it->second.mSet;
116 }
117
118 if (!acquire || stopping_)
120
122 app_, hash, m_peerSetBuilder->build());
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(j_.trace()) << "Got data (" << packet.nodes().size()
145 << ") for acquiring ledger: " << hash;
146
148
149 if (ta == nullptr)
150 {
151 peer->charge(Resource::feeUselessData, "ledger_data");
152 return;
153 }
154
156 data.reserve(packet.nodes().size());
157
158 for (auto const& node : packet.nodes())
159 {
160 if (!node.has_nodeid() || !node.has_nodedata())
161 {
162 peer->charge(Resource::feeMalformedRequest, "ledger_data");
163 return;
164 }
165
166 auto const id = deserializeSHAMapNodeID(node.nodeid());
167
168 if (!id)
169 {
170 peer->charge(Resource::feeInvalidData, "ledger_data");
171 return;
172 }
173
174 data.emplace_back(std::make_pair(*id, makeSlice(node.nodedata())));
175 }
176
177 if (!ta->takeNodes(data, peer).isUseful())
178 peer->charge(Resource::feeUselessData, "ledger_data not useful");
179 }
180
181 void
183 uint256 const& hash,
184 std::shared_ptr<SHAMap> const& set,
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
209 void
211 {
213
214 // Protect zero set from expiration
215 m_zeroSet.mSeq = seq;
216
217 if (m_seq != seq)
218 {
219 m_seq = seq;
220
221 auto it = m_map.begin();
222
223 std::uint32_t const minSeq =
224 (seq < setKeepRounds) ? 0 : (seq - setKeepRounds);
225 std::uint32_t maxSeq = seq + setKeepRounds;
226
227 while (it != m_map.end())
228 {
229 if (it->second.mSeq < minSeq || it->second.mSeq > maxSeq)
230 it = m_map.erase(it);
231 else
232 ++it;
233 }
234 }
235 }
236
237 void
238 stop() override
239 {
241 stopping_ = true;
242 m_map.clear();
243 }
244
245private:
247
249
251
252 bool stopping_{false};
255
256 // The empty transaction set whose hash is zero
258
260
262
264};
265
266//------------------------------------------------------------------------------
267
269
272 Application& app,
273 beast::insight::Collector::ptr const& collector,
274 std::function<void(std::shared_ptr<SHAMap> const&, bool)> gotSet)
275{
277 app, collector, std::move(gotSet), make_PeerSetBuilder(app));
278}
279
280} // namespace ripple
T begin(T... args)
A generic endpoint for log messages.
Definition Journal.h:60
Stream trace() const
Severity stream access functions.
Definition Journal.h:322
virtual Family & getNodeFamily()=0
InboundTransactionSet(std::uint32_t seq, std::shared_ptr< SHAMap > const &set)
TransactionAcquire::pointer mAcquire
std::shared_ptr< SHAMap > mSet
void giveSet(uint256 const &hash, std::shared_ptr< SHAMap > const &set, bool fromAcquire) override
Add a transaction set.
void newRound(std::uint32_t seq) override
Informs the container if a new consensus round.
TransactionAcquire::pointer getAcquire(uint256 const &hash)
std::function< void(std::shared_ptr< SHAMap > const &, bool)> m_gotSet
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.
InboundTransactionsImp(Application &app, beast::insight::Collector::ptr const &collector, std::function< void(std::shared_ptr< SHAMap > const &, bool)> gotSet, std::unique_ptr< PeerSetBuilder > peerSetBuilder)
std::shared_ptr< SHAMap > getSet(uint256 const &hash, bool acquire) override
Find and return a transaction set, or nullptr if it is missing.
std::unique_ptr< PeerSetBuilder > m_peerSetBuilder
Manages the acquisition and lifetime of transaction sets.
T clear(T... args)
T end(T... args)
T erase(T... args)
T find(T... args)
T is_same_v
T make_pair(T... args)
Charge const feeMalformedRequest
Schedule of fees charged for imposing load on the server.
Charge const feeInvalidData
Charge const feeUselessData
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:25
std::optional< SHAMapNodeID > deserializeSHAMapNodeID(void const *data, std::size_t size)
Return an object representing a serialized SHAMap Node ID.
base_uint< 256 > uint256
Definition base_uint.h:558
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,...
std::unique_ptr< PeerSetBuilder > make_PeerSetBuilder(Application &app)
Definition PeerSet.cpp:144
std::unique_ptr< InboundTransactions > make_InboundTransactions(Application &app, beast::insight::Collector::ptr const &collector, std::function< void(std::shared_ptr< SHAMap > const &, bool)> gotSet)
std::enable_if_t< std::is_same< T, char >::value||std::is_same< T, unsigned char >::value, Slice > makeSlice(std::array< T, N > const &a)
Definition Slice.h:244
STL namespace.