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
30#include <memory>
31#include <mutex>
32
33namespace ripple {
34
35enum {
36 // Ideal number of peers to start with
38
39 // How many rounds to keep a set
41};
42
44{
45 // A transaction set we generated, acquired, or are acquiring
46public:
50
52 : mSeq(seq), mSet(set)
53 {
54 ;
55 }
57 {
58 ;
59 }
60};
61
63{
64public:
66 Application& app,
67 beast::insight::Collector::ptr const& collector,
68 std::function<void(std::shared_ptr<SHAMap> const&, bool)> gotSet,
70 : app_(app)
71 , m_seq(0)
73 , m_gotSet(std::move(gotSet))
74 , m_peerSetBuilder(std::move(peerSetBuilder))
75 , j_(app_.journal("InboundTransactions"))
76 {
77 m_zeroSet.mSet = std::make_shared<SHAMap>(
79 m_zeroSet.mSet->setUnbacked();
80 }
81
83 getAcquire(uint256 const& hash)
84 {
85 {
87
88 auto it = m_map.find(hash);
89
90 if (it != m_map.end())
91 return it->second.mAcquire;
92 }
93 return {};
94 }
95
97 getSet(uint256 const& hash, bool acquire) override
98 {
100
101 {
103
104 if (auto it = m_map.find(hash); 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_)
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(j_.trace()) << "Got data (" << packet.nodes().size()
144 << ") for acquiring ledger: " << hash;
145
147
148 if (ta == nullptr)
149 {
150 peer->charge(Resource::feeUselessData, "ledger_data");
151 return;
152 }
153
155 data.reserve(packet.nodes().size());
156
157 for (auto const& node : packet.nodes())
158 {
159 if (!node.has_nodeid() || !node.has_nodedata())
160 {
161 peer->charge(Resource::feeMalformedRequest, "ledger_data");
162 return;
163 }
164
165 auto const id = deserializeSHAMapNodeID(node.nodeid());
166
167 if (!id)
168 {
169 peer->charge(Resource::feeInvalidData, "ledger_data");
170 return;
171 }
172
173 data.emplace_back(std::make_pair(*id, makeSlice(node.nodedata())));
174 }
175
176 if (!ta->takeNodes(data, peer).isUseful())
177 peer->charge(Resource::feeUselessData, "ledger_data not useful");
178 }
179
180 void
182 uint256 const& hash,
183 std::shared_ptr<SHAMap> const& set,
184 bool fromAcquire) override
185 {
186 bool isNew = true;
187
188 {
190
191 auto& inboundSet = m_map[hash];
192
193 if (inboundSet.mSeq < m_seq)
194 inboundSet.mSeq = m_seq;
195
196 if (inboundSet.mSet)
197 isNew = false;
198 else
199 inboundSet.mSet = set;
200
201 inboundSet.mAcquire.reset();
202 }
203
204 if (isNew)
205 m_gotSet(set, fromAcquire);
206 }
207
208 void
210 {
212
213 // Protect zero set from expiration
214 m_zeroSet.mSeq = seq;
215
216 if (m_seq != seq)
217 {
218 m_seq = seq;
219
220 auto it = m_map.begin();
221
222 std::uint32_t const minSeq =
223 (seq < setKeepRounds) ? 0 : (seq - setKeepRounds);
224 std::uint32_t maxSeq = seq + setKeepRounds;
225
226 while (it != m_map.end())
227 {
228 if (it->second.mSeq < minSeq || it->second.mSeq > maxSeq)
229 it = m_map.erase(it);
230 else
231 ++it;
232 }
233 }
234 }
235
236 void
237 stop() override
238 {
240 stopping_ = true;
241 m_map.clear();
242 }
243
244private:
246
248
250
251 bool stopping_{false};
254
255 // The empty transaction set whose hash is zero
257
259
261
263};
264
265//------------------------------------------------------------------------------
266
268
271 Application& app,
272 beast::insight::Collector::ptr const& collector,
273 std::function<void(std::shared_ptr<SHAMap> const&, bool)> gotSet)
274{
275 return std::make_unique<InboundTransactionsImp>(
276 app, collector, std::move(gotSet), make_PeerSetBuilder(app));
277}
278
279} // 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 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: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,...
Definition: BasicConfig.h:315
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.