rippled
Loading...
Searching...
No Matches
FeeVoteImpl.cpp
1#include <xrpld/app/ledger/Ledger.h>
2#include <xrpld/app/misc/FeeVote.h>
3
4#include <xrpl/beast/utility/Journal.h>
5#include <xrpl/protocol/STValidation.h>
6#include <xrpl/protocol/st.h>
7
8namespace ripple {
9
10namespace detail {
11
13{
14private:
16 value_type const current_; // The current setting
17 value_type const target_; // The setting we want
19
20public:
22 : current_(current), target_(target)
23 {
24 // Add our vote
26 }
27
28 void
30 {
31 ++voteMap_[vote];
32 }
33
34 void
36 {
38 }
39
41 current() const
42 {
43 return current_;
44 }
45
47 getVotes() const;
48};
49
50auto
51VotableValue::getVotes() const -> std::pair<value_type, bool>
52{
53 value_type ourVote = current_;
54 int weight = 0;
55 for (auto const& [key, val] : voteMap_)
56 {
57 // Take most voted value between current and target, inclusive
58 if ((key <= std::max(target_, current_)) &&
59 (key >= std::min(target_, current_)) && (val > weight))
60 {
61 ourVote = key;
62 weight = val;
63 }
64 }
65
66 return {ourVote, ourVote != current_};
67}
68
69} // namespace detail
70
71//------------------------------------------------------------------------------
72
73class FeeVoteImpl : public FeeVote
74{
75private:
78
79public:
80 FeeVoteImpl(FeeSetup const& setup, beast::Journal journal);
81
82 void
83 doValidation(Fees const& lastFees, Rules const& rules, STValidation& val)
84 override;
85
86 void
88 std::shared_ptr<ReadView const> const& lastClosedLedger,
89 std::vector<std::shared_ptr<STValidation>> const& parentValidations,
90 std::shared_ptr<SHAMap> const& initialPosition) override;
91};
92
93//--------------------------------------------------------------------------
94
96 : target_(setup), journal_(journal)
97{
98}
99
100void
102 Fees const& lastFees,
103 Rules const& rules,
104 STValidation& v)
105{
106 // Values should always be in a valid range (because the voting process
107 // will ignore out-of-range values) but if we detect such a case, we do
108 // not send a value.
109 if (rules.enabled(featureXRPFees))
110 {
111 auto vote = [&v, this](
112 auto const current,
113 XRPAmount target,
114 char const* name,
115 auto const& sfield) {
116 if (current != target)
117 {
118 JLOG(journal_.info())
119 << "Voting for " << name << " of " << target;
120
121 v[sfield] = target;
122 }
123 };
124 vote(lastFees.base, target_.reference_fee, "base fee", sfBaseFeeDrops);
125 vote(
126 lastFees.reserve,
128 "base reserve",
129 sfReserveBaseDrops);
130 vote(
131 lastFees.increment,
133 "reserve increment",
134 sfReserveIncrementDrops);
135 }
136 else
137 {
138 auto to32 = [](XRPAmount target) {
139 return target.dropsAs<std::uint32_t>();
140 };
141 auto to64 = [](XRPAmount target) {
142 return target.dropsAs<std::uint64_t>();
143 };
144 auto vote = [&v, this](
145 auto const current,
146 XRPAmount target,
147 auto const& convertCallback,
148 char const* name,
149 auto const& sfield) {
150 if (current != target)
151 {
152 JLOG(journal_.info())
153 << "Voting for " << name << " of " << target;
154
155 if (auto const f = convertCallback(target))
156 v[sfield] = *f;
157 }
158 };
159
160 vote(lastFees.base, target_.reference_fee, to64, "base fee", sfBaseFee);
161 vote(
162 lastFees.reserve,
164 to32,
165 "base reserve",
166 sfReserveBase);
167 vote(
168 lastFees.increment,
170 to32,
171 "reserve increment",
172 sfReserveIncrement);
173 }
174}
175
176void
178 std::shared_ptr<ReadView const> const& lastClosedLedger,
180 std::shared_ptr<SHAMap> const& initialPosition)
181{
182 // LCL must be flag ledger
183 XRPL_ASSERT(
184 lastClosedLedger && isFlagLedger(lastClosedLedger->seq()),
185 "ripple::FeeVoteImpl::doVoting : has a flag ledger");
186
187 detail::VotableValue baseFeeVote(
188 lastClosedLedger->fees().base, target_.reference_fee);
189
190 detail::VotableValue baseReserveVote(
191 lastClosedLedger->fees().reserve, target_.account_reserve);
192
193 detail::VotableValue incReserveVote(
194 lastClosedLedger->fees().increment, target_.owner_reserve);
195
196 auto const& rules = lastClosedLedger->rules();
197 if (rules.enabled(featureXRPFees))
198 {
199 auto doVote = [](std::shared_ptr<STValidation> const& val,
201 SF_AMOUNT const& xrpField) {
202 if (auto const field = ~val->at(~xrpField);
203 field && field->native())
204 {
205 auto const vote = field->xrp();
206 if (isLegalAmountSigned(vote))
207 value.addVote(vote);
208 else
209 value.noVote();
210 }
211 else
212 {
213 value.noVote();
214 }
215 };
216
217 for (auto const& val : set)
218 {
219 if (!val->isTrusted())
220 continue;
221 doVote(val, baseFeeVote, sfBaseFeeDrops);
222 doVote(val, baseReserveVote, sfReserveBaseDrops);
223 doVote(val, incReserveVote, sfReserveIncrementDrops);
224 }
225 }
226 else
227 {
228 auto doVote = [](std::shared_ptr<STValidation> const& val,
230 auto const& valueField) {
231 if (auto const field = val->at(~valueField))
232 {
233 using xrptype = XRPAmount::value_type;
234 auto const vote = *field;
235 if (vote <= std::numeric_limits<xrptype>::max() &&
236 isLegalAmountSigned(XRPAmount{unsafe_cast<xrptype>(vote)}))
237 value.addVote(
238 XRPAmount{unsafe_cast<XRPAmount::value_type>(vote)});
239 else
240 // Invalid amounts will be treated as if they're
241 // not provided. Don't throw because this value is
242 // provided by an external entity.
243 value.noVote();
244 }
245 else
246 {
247 value.noVote();
248 }
249 };
250
251 for (auto const& val : set)
252 {
253 if (!val->isTrusted())
254 continue;
255 doVote(val, baseFeeVote, sfBaseFee);
256 doVote(val, baseReserveVote, sfReserveBase);
257 doVote(val, incReserveVote, sfReserveIncrement);
258 }
259 }
260
261 // choose our positions
262 // TODO: Use structured binding once LLVM 16 is the minimum supported
263 // version. See also: https://github.com/llvm/llvm-project/issues/48582
264 // https://github.com/llvm/llvm-project/commit/127bf44385424891eb04cff8e52d3f157fc2cb7c
265 auto const baseFee = baseFeeVote.getVotes();
266 auto const baseReserve = baseReserveVote.getVotes();
267 auto const incReserve = incReserveVote.getVotes();
268
269 auto const seq = lastClosedLedger->info().seq + 1;
270
271 // add transactions to our position
272 if (baseFee.second || baseReserve.second || incReserve.second)
273 {
274 JLOG(journal_.warn())
275 << "We are voting for a fee change: " << baseFee.first << "/"
276 << baseReserve.first << "/" << incReserve.first;
277
278 STTx feeTx(ttFEE, [=, &rules](auto& obj) {
279 obj[sfAccount] = AccountID();
280 obj[sfLedgerSequence] = seq;
281 if (rules.enabled(featureXRPFees))
282 {
283 obj[sfBaseFeeDrops] = baseFee.first;
284 obj[sfReserveBaseDrops] = baseReserve.first;
285 obj[sfReserveIncrementDrops] = incReserve.first;
286 }
287 else
288 {
289 // Without the featureXRPFees amendment, these fields are
290 // required.
291 obj[sfBaseFee] =
292 baseFee.first.dropsAs<std::uint64_t>(baseFeeVote.current());
293 obj[sfReserveBase] = baseReserve.first.dropsAs<std::uint32_t>(
294 baseReserveVote.current());
295 obj[sfReserveIncrement] =
296 incReserve.first.dropsAs<std::uint32_t>(
297 incReserveVote.current());
298 obj[sfReferenceFeeUnits] = Config::FEE_UNITS_DEPRECATED;
299 }
300 });
301
302 uint256 txID = feeTx.getTransactionID();
303
304 JLOG(journal_.warn()) << "Vote: " << txID;
305
306 Serializer s;
307 feeTx.add(s);
308
309 if (!initialPosition->addGiveItem(
311 make_shamapitem(txID, s.slice())))
312 {
313 JLOG(journal_.warn()) << "Ledger already had fee change";
314 }
315 }
316}
317
318//------------------------------------------------------------------------------
319
322{
323 return std::make_unique<FeeVoteImpl>(setup, journal);
324}
325
326} // namespace ripple
A generic endpoint for log messages.
Definition Journal.h:41
Stream info() const
Definition Journal.h:315
Stream warn() const
Definition Journal.h:321
static constexpr std::uint32_t FEE_UNITS_DEPRECATED
Definition Config.h:141
void doValidation(Fees const &lastFees, Rules const &rules, STValidation &val) override
Add local fee preference to validation.
void doVoting(std::shared_ptr< ReadView const > const &lastClosedLedger, std::vector< std::shared_ptr< STValidation > > const &parentValidations, std::shared_ptr< SHAMap > const &initialPosition) override
Cast our local vote on the fee.
FeeVoteImpl(FeeSetup const &setup, beast::Journal journal)
beast::Journal const journal_
Manager to process fee votes.
Definition FeeVote.h:12
Rules controlling protocol behavior.
Definition Rules.h:19
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
Definition Rules.cpp:111
Slice slice() const noexcept
Definition Serializer.h:47
std::int64_t value_type
Definition XRPAmount.h:27
VotableValue(value_type current, value_type target)
std::pair< value_type, bool > getVotes() const
std::map< value_type, int > voteMap_
void addVote(value_type vote)
value_type current() const
T is_same_v
T max(T... args)
T min(T... args)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
base_uint< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Definition AccountID.h:29
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,...
bool isLegalAmountSigned(XRPAmount const &amount)
Returns true if the absolute value of the amount does not exceed the initial XRP in existence.
std::unique_ptr< FeeVote > make_FeeVote(FeeSetup const &setup, beast::Journal journal)
Create an instance of the FeeVote logic.
@ current
This was a new validation and was added.
bool isFlagLedger(LedgerIndex seq)
Returns true if the given ledgerIndex is a flag ledgerIndex.
Definition Ledger.cpp:942
boost::intrusive_ptr< SHAMapItem > make_shamapitem(uint256 const &tag, Slice data)
Definition SHAMapItem.h:142
STL namespace.
Fee schedule for startup / standalone, and to vote for.
Definition Config.h:47
XRPAmount reference_fee
The cost of a reference transaction in drops.
Definition Config.h:49
XRPAmount owner_reserve
The per-owned item reserve requirement in drops.
Definition Config.h:55
XRPAmount account_reserve
The account reserve requirement in drops.
Definition Config.h:52
Reflects the fee settings for a particular ledger.
XRPAmount base
XRPAmount increment
XRPAmount reserve
A field with a type known at compile time.
Definition SField.h:301