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 xrpl {
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 {
23 // Add our vote
25 }
26
27 void
29 {
30 ++voteMap_[vote];
31 }
32
33 void
35 {
37 }
38
40 current() const
41 {
42 return current_;
43 }
44
46 getVotes() const;
47};
48
49auto
50VotableValue::getVotes() const -> std::pair<value_type, bool>
51{
52 value_type ourVote = current_;
53 int weight = 0;
54 for (auto const& [key, val] : voteMap_)
55 {
56 // Take most voted value between current and target, inclusive
57 if ((key <= std::max(target_, current_)) && (key >= std::min(target_, current_)) && (val > weight))
58 {
59 ourVote = key;
60 weight = val;
61 }
62 }
63
64 return {ourVote, ourVote != current_};
65}
66
67} // namespace detail
68
69//------------------------------------------------------------------------------
70
71class FeeVoteImpl : public FeeVote
72{
73private:
76
77public:
78 FeeVoteImpl(FeeSetup const& setup, beast::Journal journal);
79
80 void
81 doValidation(Fees const& lastFees, Rules const& rules, STValidation& val) override;
82
83 void
85 std::shared_ptr<ReadView const> const& lastClosedLedger,
86 std::vector<std::shared_ptr<STValidation>> const& parentValidations,
87 std::shared_ptr<SHAMap> const& initialPosition) override;
88};
89
90//--------------------------------------------------------------------------
91
92FeeVoteImpl::FeeVoteImpl(FeeSetup const& setup, beast::Journal journal) : target_(setup), journal_(journal)
93{
94}
95
96void
97FeeVoteImpl::doValidation(Fees const& lastFees, Rules const& rules, STValidation& v)
98{
99 // Values should always be in a valid range (because the voting process
100 // will ignore out-of-range values) but if we detect such a case, we do
101 // not send a value.
102 if (rules.enabled(featureXRPFees))
103 {
104 auto vote = [&v, this](auto const current, XRPAmount target, char const* name, auto const& sfield) {
105 if (current != target)
106 {
107 JLOG(journal_.info()) << "Voting for " << name << " of " << target;
108
109 v[sfield] = target;
110 }
111 };
112 vote(lastFees.base, target_.reference_fee, "base fee", sfBaseFeeDrops);
113 vote(lastFees.reserve, target_.account_reserve, "base reserve", sfReserveBaseDrops);
114 vote(lastFees.increment, target_.owner_reserve, "reserve increment", sfReserveIncrementDrops);
115 }
116 else
117 {
118 auto to32 = [](XRPAmount target) { return target.dropsAs<std::uint32_t>(); };
119 auto to64 = [](XRPAmount target) { return target.dropsAs<std::uint64_t>(); };
120 auto vote = [&v, this](
121 auto const current,
122 XRPAmount target,
123 auto const& convertCallback,
124 char const* name,
125 auto const& sfield) {
126 if (current != target)
127 {
128 JLOG(journal_.info()) << "Voting for " << name << " of " << target;
129
130 if (auto const f = convertCallback(target))
131 v[sfield] = *f;
132 }
133 };
134
135 vote(lastFees.base, target_.reference_fee, to64, "base fee", sfBaseFee);
136 vote(lastFees.reserve, target_.account_reserve, to32, "base reserve", sfReserveBase);
137 vote(lastFees.increment, target_.owner_reserve, to32, "reserve increment", sfReserveIncrement);
138 }
139}
140
141void
143 std::shared_ptr<ReadView const> const& lastClosedLedger,
145 std::shared_ptr<SHAMap> const& initialPosition)
146{
147 // LCL must be flag ledger
148 XRPL_ASSERT(
149 lastClosedLedger && isFlagLedger(lastClosedLedger->seq()), "xrpl::FeeVoteImpl::doVoting : has a flag ledger");
150
151 detail::VotableValue baseFeeVote(lastClosedLedger->fees().base, target_.reference_fee);
152
153 detail::VotableValue baseReserveVote(lastClosedLedger->fees().reserve, target_.account_reserve);
154
155 detail::VotableValue incReserveVote(lastClosedLedger->fees().increment, target_.owner_reserve);
156
157 auto const& rules = lastClosedLedger->rules();
158 if (rules.enabled(featureXRPFees))
159 {
160 auto doVote =
161 [](std::shared_ptr<STValidation> const& val, detail::VotableValue& value, SF_AMOUNT const& xrpField) {
162 if (auto const field = ~val->at(~xrpField); field && field->native())
163 {
164 auto const vote = field->xrp();
165 if (isLegalAmountSigned(vote))
166 value.addVote(vote);
167 else
168 value.noVote();
169 }
170 else
171 {
172 value.noVote();
173 }
174 };
175
176 for (auto const& val : set)
177 {
178 if (!val->isTrusted())
179 continue;
180 doVote(val, baseFeeVote, sfBaseFeeDrops);
181 doVote(val, baseReserveVote, sfReserveBaseDrops);
182 doVote(val, incReserveVote, sfReserveIncrementDrops);
183 }
184 }
185 else
186 {
187 auto doVote =
188 [](std::shared_ptr<STValidation> const& val, detail::VotableValue& value, auto const& valueField) {
189 if (auto const field = val->at(~valueField))
190 {
191 using XRPType = XRPAmount::value_type;
192 auto const vote = *field;
193 if (vote <= std::numeric_limits<XRPType>::max() &&
194 isLegalAmountSigned(XRPAmount{unsafe_cast<XRPType>(vote)}))
195 value.addVote(XRPAmount{unsafe_cast<XRPType>(vote)});
196 else
197 // Invalid amounts will be treated as if they're
198 // not provided. Don't throw because this value is
199 // provided by an external entity.
200 value.noVote();
201 }
202 else
203 {
204 value.noVote();
205 }
206 };
207
208 for (auto const& val : set)
209 {
210 if (!val->isTrusted())
211 continue;
212 doVote(val, baseFeeVote, sfBaseFee);
213 doVote(val, baseReserveVote, sfReserveBase);
214 doVote(val, incReserveVote, sfReserveIncrement);
215 }
216 }
217
218 // choose our positions
219 // TODO: Use structured binding once LLVM 16 is the minimum supported
220 // version. See also: https://github.com/llvm/llvm-project/issues/48582
221 // https://github.com/llvm/llvm-project/commit/127bf44385424891eb04cff8e52d3f157fc2cb7c
222 auto const baseFee = baseFeeVote.getVotes();
223 auto const baseReserve = baseReserveVote.getVotes();
224 auto const incReserve = incReserveVote.getVotes();
225
226 auto const seq = lastClosedLedger->header().seq + 1;
227
228 // add transactions to our position
229 if (baseFee.second || baseReserve.second || incReserve.second)
230 {
231 JLOG(journal_.warn()) << "We are voting for a fee change: " << baseFee.first << "/" << baseReserve.first << "/"
232 << incReserve.first;
233
234 STTx feeTx(ttFEE, [=, &rules](auto& obj) {
235 obj[sfAccount] = AccountID();
236 obj[sfLedgerSequence] = seq;
237 if (rules.enabled(featureXRPFees))
238 {
239 obj[sfBaseFeeDrops] = baseFee.first;
240 obj[sfReserveBaseDrops] = baseReserve.first;
241 obj[sfReserveIncrementDrops] = incReserve.first;
242 }
243 else
244 {
245 // Without the featureXRPFees amendment, these fields are
246 // required.
247 obj[sfBaseFee] = baseFee.first.dropsAs<std::uint64_t>(baseFeeVote.current());
248 obj[sfReserveBase] = baseReserve.first.dropsAs<std::uint32_t>(baseReserveVote.current());
249 obj[sfReserveIncrement] = incReserve.first.dropsAs<std::uint32_t>(incReserveVote.current());
250 obj[sfReferenceFeeUnits] = Config::FEE_UNITS_DEPRECATED;
251 }
252 });
253
254 uint256 txID = feeTx.getTransactionID();
255
256 JLOG(journal_.warn()) << "Vote: " << txID;
257
258 Serializer s;
259 feeTx.add(s);
260
261 if (!initialPosition->addGiveItem(SHAMapNodeType::tnTRANSACTION_NM, make_shamapitem(txID, s.slice())))
262 {
263 JLOG(journal_.warn()) << "Ledger already had fee change";
264 }
265 }
266}
267
268//------------------------------------------------------------------------------
269
272{
273 return std::make_unique<FeeVoteImpl>(setup, journal);
274}
275
276} // namespace xrpl
A generic endpoint for log messages.
Definition Journal.h:41
Stream info() const
Definition Journal.h:307
Stream warn() const
Definition Journal.h:313
static constexpr std::uint32_t FEE_UNITS_DEPRECATED
Definition Config.h:142
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: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:118
Slice slice() const noexcept
Definition Serializer.h:45
std::int64_t value_type
Definition XRPAmount.h:27
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:6
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 Ledger.cpp:891
boost::intrusive_ptr< SHAMapItem > make_shamapitem(uint256 const &tag, Slice data)
Definition SHAMapItem.h:138
base_uint< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Definition AccountID.h:29
@ current
This was a new validation and was added.
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:47
XRPAmount reference_fee
The cost of a reference transaction in drops.
Definition Config.h:49
XRPAmount account_reserve
The account reserve requirement in drops.
Definition Config.h:52
XRPAmount owner_reserve
The per-owned item reserve requirement in drops.
Definition Config.h:55
Reflects the fee settings for a particular ledger.
XRPAmount reserve
XRPAmount increment
XRPAmount base
A field with a type known at compile time.
Definition SField.h:302