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#include <xrpl/basics/Log.h>
27#include <xrpl/protocol/RippleLedgerHash.h>
28#include <xrpl/resource/Fees.h>
29#include <memory>
30#include <mutex>
31
32namespace ripple {
33
34enum {
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
45public:
49
51 : mSeq(seq), mSet(set)
52 {
53 ;
54 }
56 {
57 ;
58 }
59};
60
62{
63public:
65 Application& app,
66 beast::insight::Collector::ptr const& collector,
67 std::function<void(std::shared_ptr<SHAMap> const&, bool)> gotSet,
69 : app_(app)
70 , m_seq(0)
72 , m_gotSet(std::move(gotSet))
73 , m_peerSetBuilder(std::move(peerSetBuilder))
74 , j_(app_.journal("InboundTransactions"))
75 {
76 m_zeroSet.mSet = std::make_shared<SHAMap>(
78 m_zeroSet.mSet->setUnbacked();
79 }
80
82 getAcquire(uint256 const& hash)
83 {
84 {
86
87 auto it = m_map.find(hash);
88
89 if (it != m_map.end())
90 return it->second.mAcquire;
91 }
92 return {};
93 }
94
96 getSet(uint256 const& hash, bool acquire) override
97 {
99
100 {
102
103 if (auto it = m_map.find(hash); it != m_map.end())
104 {
105 if (acquire)
106 {
107 it->second.mSeq = m_seq;
108 if (it->second.mAcquire)
109 {
110 it->second.mAcquire->stillNeed();
111 }
112 }
113 return it->second.mSet;
114 }
115
116 if (!acquire || stopping_)
118
119 ta = std::make_shared<TransactionAcquire>(
120 app_, hash, m_peerSetBuilder->build());
121
122 auto& obj = m_map[hash];
123 obj.mAcquire = ta;
124 obj.mSeq = m_seq;
125 }
126
127 ta->init(startPeers);
128
129 return {};
130 }
131
134 void
136 LedgerHash const& hash,
138 std::shared_ptr<protocol::TMLedgerData> packet_ptr) override
139 {
140 protocol::TMLedgerData& packet = *packet_ptr;
141
142 JLOG(j_.trace()) << "Got data (" << packet.nodes().size()
143 << ") for acquiring ledger: " << hash;
144
146
147 if (ta == nullptr)
148 {
149 peer->charge(Resource::feeUselessData, "ledger_data");
150 return;
151 }
152
154 data.reserve(packet.nodes().size());
155
156 for (auto const& node : packet.nodes())
157 {
158 if (!node.has_nodeid() || !node.has_nodedata())
159 {
160 peer->charge(Resource::feeMalformedRequest, "ledger_data");
161 return;
162 }
163
164 auto const id = deserializeSHAMapNodeID(node.nodeid());
165
166 if (!id)
167 {
168 peer->charge(Resource::feeInvalidData, "ledger_data");
169 return;
170 }
171
172 data.emplace_back(std::make_pair(*id, makeSlice(node.nodedata())));
173 }
174
175 if (!ta->takeNodes(data, peer).isUseful())
176 peer->charge(Resource::feeUselessData, "ledger_data not useful");
177 }
178
179 void
181 uint256 const& hash,
182 std::shared_ptr<SHAMap> const& set,
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
209 {
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 stop() override
237 {
239 stopping_ = true;
240 m_map.clear();
241 }
242
243private:
245
247
249
250 bool stopping_{false};
253
254 // The empty transaction set whose hash is zero
256
258
260
262};
263
264//------------------------------------------------------------------------------
265
267
270 Application& app,
271 beast::insight::Collector::ptr const& collector,
272 std::function<void(std::shared_ptr<SHAMap> const&, bool)> gotSet)
273{
274 return std::make_unique<InboundTransactionsImp>(
275 app, collector, std::move(gotSet), make_PeerSetBuilder(app));
276}
277
278} // namespace ripple
T begin(T... args)
A generic endpoint for log messages.
Definition: Journal.h:59
Stream trace() const
Severity stream access functions.
Definition: Journal.h:311
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 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:26
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:557
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:316
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:243
STL namespace.