rippled
Loading...
Searching...
No Matches
InboundTransactions.cpp
1#include <xrpld/app/ledger/InboundLedgers.h>
2#include <xrpld/app/ledger/InboundTransactions.h>
3#include <xrpld/app/ledger/detail/TransactionAcquire.h>
4#include <xrpld/app/main/Application.h>
5
6#include <xrpl/core/JobQueue.h>
7#include <xrpl/protocol/RippleLedgerHash.h>
8#include <xrpl/resource/Fees.h>
9#include <xrpl/server/NetworkOPs.h>
10
11#include <algorithm>
12#include <memory>
13#include <mutex>
14
15namespace xrpl {
16
17enum {
18 // Ideal number of peers to start with
20
21 // How many rounds to keep a set
23};
24
26{
27 // A transaction set we generated, acquired, or are acquiring
28public:
32
34 : mSeq(seq), mSet(set)
35 {
36 ;
37 }
39 {
40 ;
41 }
42};
43
45{
46public:
48 Application& app,
49 beast::insight::Collector::ptr const& collector,
50 std::function<void(std::shared_ptr<SHAMap> const&, bool)> gotSet,
52 : app_(app)
54 , m_gotSet(std::move(gotSet))
55 , m_peerSetBuilder(std::move(peerSetBuilder))
56 , j_(app_.getJournal("InboundTransactions"))
57 {
60 m_zeroSet.mSet->setUnbacked();
61 }
62
64 getAcquire(uint256 const& hash)
65 {
66 {
67 std::lock_guard const sl(mLock);
68
69 auto it = m_map.find(hash);
70
71 if (it != m_map.end())
72 return it->second.mAcquire;
73 }
74 return {};
75 }
76
78 getSet(uint256 const& hash, bool acquire) override
79 {
81
82 {
83 std::lock_guard const sl(mLock);
84
85 if (auto it = m_map.find(hash); it != m_map.end())
86 {
87 if (acquire)
88 {
89 it->second.mSeq = m_seq;
90 if (it->second.mAcquire)
91 {
92 it->second.mAcquire->stillNeed();
93 }
94 }
95 return it->second.mSet;
96 }
97
98 if (!acquire || stopping_)
100
102
103 auto& obj = m_map[hash];
104 obj.mAcquire = ta;
105 obj.mSeq = m_seq;
106 }
107
108 ta->init(startPeers);
109
110 return {};
111 }
112
115 void
117 LedgerHash const& hash,
119 std::shared_ptr<protocol::TMLedgerData> packet_ptr) override
120 {
121 protocol::TMLedgerData const& packet = *packet_ptr;
122
123 JLOG(j_.trace()) << "Got data (" << packet.nodes().size()
124 << ") for acquiring ledger: " << hash;
125
127
128 if (ta == nullptr)
129 {
130 peer->charge(Resource::feeUselessData, "ledger_data");
131 return;
132 }
133
135 data.reserve(packet.nodes().size());
136
137 for (auto const& node : packet.nodes())
138 {
139 if (!node.has_nodeid() || !node.has_nodedata())
140 {
141 peer->charge(Resource::feeMalformedRequest, "ledger_data");
142 return;
143 }
144
145 auto const id = deserializeSHAMapNodeID(node.nodeid());
146
147 if (!id)
148 {
149 peer->charge(Resource::feeInvalidData, "ledger_data");
150 return;
151 }
152
153 data.emplace_back(std::make_pair(*id, makeSlice(node.nodedata())));
154 }
155
156 if (!ta->takeNodes(data, peer).isUseful())
157 peer->charge(Resource::feeUselessData, "ledger_data not useful");
158 }
159
160 void
161 giveSet(uint256 const& hash, std::shared_ptr<SHAMap> const& set, bool fromAcquire) override
162 {
163 bool isNew = true;
164
165 {
166 std::lock_guard const sl(mLock);
167
168 auto& inboundSet = m_map[hash];
169
170 inboundSet.mSeq = std::max(inboundSet.mSeq, m_seq);
171
172 if (inboundSet.mSet)
173 {
174 isNew = false;
175 }
176 else
177 {
178 inboundSet.mSet = set;
179 }
180
181 inboundSet.mAcquire.reset();
182 }
183
184 if (isNew)
185 m_gotSet(set, fromAcquire);
186 }
187
188 void
190 {
191 std::lock_guard const lock(mLock);
192
193 // Protect zero set from expiration
194 m_zeroSet.mSeq = seq;
195
196 if (m_seq != seq)
197 {
198 m_seq = seq;
199
200 auto it = m_map.begin();
201
202 std::uint32_t const minSeq = (seq < setKeepRounds) ? 0 : (seq - setKeepRounds);
203 std::uint32_t const maxSeq = seq + setKeepRounds;
204
205 while (it != m_map.end())
206 {
207 if (it->second.mSeq < minSeq || it->second.mSeq > maxSeq)
208 {
209 it = m_map.erase(it);
210 }
211 else
212 {
213 ++it;
214 }
215 }
216 }
217 }
218
219 void
220 stop() override
221 {
222 std::lock_guard const lock(mLock);
223 stopping_ = true;
224 m_map.clear();
225 }
226
227private:
229
231
233
234 bool stopping_{false};
237
238 // The empty transaction set whose hash is zero
240
242
244
246};
247
248//------------------------------------------------------------------------------
249
251
254 Application& app,
255 beast::insight::Collector::ptr const& collector,
256 std::function<void(std::shared_ptr<SHAMap> const&, bool)> gotSet)
257{
259 app, collector, std::move(gotSet), make_PeerSetBuilder(app));
260}
261
262} // namespace xrpl
T begin(T... args)
A generic endpoint for log messages.
Definition Journal.h:40
Stream trace() const
Severity stream access functions.
Definition Journal.h:295
std::shared_ptr< SHAMap > mSet
TransactionAcquire::pointer mAcquire
InboundTransactionSet(std::uint32_t seq, std::shared_ptr< SHAMap > const &set)
void giveSet(uint256 const &hash, std::shared_ptr< SHAMap > const &set, bool fromAcquire) override
Add a transaction set.
InboundTransactionSet & m_zeroSet
TransactionAcquire::pointer getAcquire(uint256 const &hash)
std::unique_ptr< PeerSetBuilder > m_peerSetBuilder
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.
void newRound(std::uint32_t seq) override
Informs the container if a new consensus round.
std::shared_ptr< SHAMap > getSet(uint256 const &hash, bool acquire) override
Find and return a transaction set, or nullptr if it is missing.
InboundTransactionsImp(Application &app, beast::insight::Collector::ptr const &collector, std::function< void(std::shared_ptr< SHAMap > const &, bool)> gotSet, std::unique_ptr< PeerSetBuilder > peerSetBuilder)
Manages the acquisition and lifetime of transaction sets.
virtual ~InboundTransactions()=0
virtual Family & getNodeFamily()=0
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)
T max(T... args)
STL namespace.
Charge const feeInvalidData
Charge const feeMalformedRequest
Schedule of fees charged for imposing load on the server.
Charge const feeUselessData
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
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,...
base_uint< 256 > uint256
Definition base_uint.h:531
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::optional< SHAMapNodeID > deserializeSHAMapNodeID(void const *data, std::size_t size)
Return an object representing a serialized SHAMap Node ID.
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:215
std::unique_ptr< PeerSetBuilder > make_PeerSetBuilder(Application &app)
Definition PeerSet.cpp:122