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