rippled
FeeVoteImpl.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 <ripple/app/main/Application.h>
21 #include <ripple/app/misc/FeeVote.h>
22 #include <ripple/basics/BasicConfig.h>
23 #include <ripple/beast/utility/Journal.h>
24 #include <ripple/protocol/STValidation.h>
25 #include <ripple/protocol/st.h>
26 
27 namespace ripple {
28 
29 namespace detail {
30 
32 {
33 private:
35  value_type const mCurrent; // The current setting
36  value_type const mTarget; // The setting we want
38 
39 public:
41  : mCurrent(current), mTarget(target)
42  {
43  // Add our vote
44  ++mVoteMap[mTarget];
45  }
46 
47  void
49  {
50  ++mVoteMap[vote];
51  }
52 
53  void
55  {
57  }
58 
60  getVotes() const;
61 };
62 
63 auto
65 {
66  value_type ourVote = mCurrent;
67  int weight = 0;
68  for (auto const& [key, val] : mVoteMap)
69  {
70  // Take most voted value between current and target, inclusive
71  if ((key <= std::max(mTarget, mCurrent)) &&
72  (key >= std::min(mTarget, mCurrent)) && (val > weight))
73  {
74  ourVote = key;
75  weight = val;
76  }
77  }
78 
79  return ourVote;
80 }
81 
82 } // namespace detail
83 
84 //------------------------------------------------------------------------------
85 
86 class FeeVoteImpl : public FeeVote
87 {
88 private:
89  Setup target_;
91 
92 public:
93  FeeVoteImpl(Setup const& setup, beast::Journal journal);
94 
95  void
96  doValidation(Fees const& lastFees, STValidation& val) override;
97 
98  void
99  doVoting(
100  std::shared_ptr<ReadView const> const& lastClosedLedger,
101  std::vector<std::shared_ptr<STValidation>> const& parentValidations,
102  std::shared_ptr<SHAMap> const& initialPosition) override;
103 };
104 
105 //--------------------------------------------------------------------------
106 
107 FeeVoteImpl::FeeVoteImpl(Setup const& setup, beast::Journal journal)
108  : target_(setup), journal_(journal)
109 {
110 }
111 
112 void
114 {
115  // Values should always be in a valid range (because the voting process
116  // will ignore out-of-range values) but if we detect such a case, we do
117  // not send a value.
118  if (lastFees.base != target_.reference_fee)
119  {
120  JLOG(journal_.info())
121  << "Voting for base fee of " << target_.reference_fee;
122 
123  if (auto const f = target_.reference_fee.dropsAs<std::uint64_t>())
124  v.setFieldU64(sfBaseFee, *f);
125  }
126 
127  if (lastFees.accountReserve(0) != target_.account_reserve)
128  {
129  JLOG(journal_.info())
130  << "Voting for base reserve of " << target_.account_reserve;
131 
132  if (auto const f = target_.account_reserve.dropsAs<std::uint32_t>())
133  v.setFieldU32(sfReserveBase, *f);
134  }
135 
136  if (lastFees.increment != target_.owner_reserve)
137  {
138  JLOG(journal_.info())
139  << "Voting for reserve increment of " << target_.owner_reserve;
140 
141  if (auto const f = target_.owner_reserve.dropsAs<std::uint32_t>())
143  }
144 }
145 
146 void
148  std::shared_ptr<ReadView const> const& lastClosedLedger,
150  std::shared_ptr<SHAMap> const& initialPosition)
151 {
152  // LCL must be flag ledger
153  assert((lastClosedLedger->info().seq % 256) == 0);
154 
155  detail::VotableValue baseFeeVote(
156  lastClosedLedger->fees().base, target_.reference_fee);
157 
158  detail::VotableValue baseReserveVote(
159  lastClosedLedger->fees().accountReserve(0), target_.account_reserve);
160 
161  detail::VotableValue incReserveVote(
162  lastClosedLedger->fees().increment, target_.owner_reserve);
163 
164  for (auto const& val : set)
165  {
166  if (val->isTrusted())
167  {
168  if (val->isFieldPresent(sfBaseFee))
169  {
170  using xrptype = XRPAmount::value_type;
171  auto const vote = val->getFieldU64(sfBaseFee);
172  if (vote <= std::numeric_limits<xrptype>::max() &&
173  isLegalAmount(XRPAmount{unsafe_cast<xrptype>(vote)}))
174  baseFeeVote.addVote(
175  XRPAmount{unsafe_cast<XRPAmount::value_type>(vote)});
176  else
177  // Invalid amounts will be treated as if they're
178  // not provided. Don't throw because this value is
179  // provided by an external entity.
180  baseFeeVote.noVote();
181  }
182  else
183  {
184  baseFeeVote.noVote();
185  }
186 
187  if (val->isFieldPresent(sfReserveBase))
188  {
189  baseReserveVote.addVote(
190  XRPAmount{val->getFieldU32(sfReserveBase)});
191  }
192  else
193  {
194  baseReserveVote.noVote();
195  }
196 
197  if (val->isFieldPresent(sfReserveIncrement))
198  {
199  incReserveVote.addVote(
200  XRPAmount{val->getFieldU32(sfReserveIncrement)});
201  }
202  else
203  {
204  incReserveVote.noVote();
205  }
206  }
207  }
208 
209  // choose our positions
210  // If any of the values are invalid, send the current values.
211  auto const baseFee = baseFeeVote.getVotes().dropsAs<std::uint64_t>(
212  lastClosedLedger->fees().base);
213  auto const baseReserve = baseReserveVote.getVotes().dropsAs<std::uint32_t>(
214  lastClosedLedger->fees().accountReserve(0));
215  auto const incReserve = incReserveVote.getVotes().dropsAs<std::uint32_t>(
216  lastClosedLedger->fees().increment);
217  constexpr FeeUnit32 feeUnits = Setup::reference_fee_units;
218  auto const seq = lastClosedLedger->info().seq + 1;
219 
220  // add transactions to our position
221  if ((baseFee != lastClosedLedger->fees().base) ||
222  (baseReserve != lastClosedLedger->fees().accountReserve(0)) ||
223  (incReserve != lastClosedLedger->fees().increment))
224  {
225  JLOG(journal_.warn()) << "We are voting for a fee change: " << baseFee
226  << "/" << baseReserve << "/" << incReserve;
227 
228  STTx feeTx(
229  ttFEE,
230  [seq, baseFee, baseReserve, incReserve, feeUnits](auto& obj) {
231  obj[sfAccount] = AccountID();
232  obj[sfLedgerSequence] = seq;
233  obj[sfBaseFee] = baseFee;
234  obj[sfReserveBase] = baseReserve;
235  obj[sfReserveIncrement] = incReserve;
236  obj[sfReferenceFeeUnits] = feeUnits.fee();
237  });
238 
239  uint256 txID = feeTx.getTransactionID();
240 
241  JLOG(journal_.warn()) << "Vote: " << txID;
242 
243  Serializer s;
244  feeTx.add(s);
245 
246  auto tItem = std::make_shared<SHAMapItem>(txID, s.peekData());
247 
248  if (!initialPosition->addGiveItem(tItem, true, false))
249  {
250  JLOG(journal_.warn()) << "Ledger already had fee change";
251  }
252  }
253 }
254 
255 //------------------------------------------------------------------------------
256 
258 setup_FeeVote(Section const& section)
259 {
260  FeeVote::Setup setup;
261  {
262  std::uint64_t temp;
263  if (set(temp, "reference_fee", section) &&
265  setup.reference_fee = temp;
266  }
267  {
268  std::uint32_t temp;
269  if (set(temp, "account_reserve", section))
270  setup.account_reserve = temp;
271  if (set(temp, "owner_reserve", section))
272  setup.owner_reserve = temp;
273  }
274  return setup;
275 }
276 
279 {
280  return std::make_unique<FeeVoteImpl>(setup, journal);
281 }
282 
283 } // namespace ripple
ripple::setup_FeeVote
FeeVote::Setup setup_FeeVote(Section const &section)
Build FeeVote::Setup from a config section.
Definition: FeeVoteImpl.cpp:258
ripple::Section
Holds a collection of configuration values.
Definition: BasicConfig.h:43
ripple::FeeVote::Setup::owner_reserve
XRPAmount owner_reserve
The per-owned item reserve requirement in drops.
Definition: FeeVote.h:52
std::shared_ptr
STL class.
ripple::isLegalAmount
bool isLegalAmount(XRPAmount const &amount)
Returns true if the amount does not exceed the initial XRP in existence.
Definition: SystemParameters.h:46
ripple::make_FeeVote
std::unique_ptr< FeeVote > make_FeeVote(FeeVote::Setup const &setup, beast::Journal journal)
Create an instance of the FeeVote logic.
Definition: FeeVoteImpl.cpp:278
ripple::FeeVote
Manager to process fee votes.
Definition: FeeVote.h:32
ripple::FeeVote::Setup::reference_fee
XRPAmount reference_fee
The cost of a reference transaction in drops.
Definition: FeeVote.h:43
std::vector
STL class.
ripple::detail::VotableValue::noVote
void noVote()
Definition: FeeVoteImpl.cpp:54
ripple::sfAccount
const SF_Account sfAccount(access, STI_ACCOUNT, 1, "Account")
Definition: SField.h:476
ripple::FeeVoteImpl::doValidation
void doValidation(Fees const &lastFees, STValidation &val) override
Add local fee preference to validation.
Definition: FeeVoteImpl.cpp:113
beast::Journal::warn
Stream warn() const
Definition: Journal.h:327
ripple::FeeVote::Setup
Fee schedule to vote for.
Definition: FeeVote.h:40
ripple::detail::VotableValue::VotableValue
VotableValue(value_type current, value_type target)
Definition: FeeVoteImpl.cpp:40
ripple::sfReserveBase
const SF_U32 sfReserveBase(access, STI_UINT32, 31, "ReserveBase")
Definition: SField.h:383
ripple::FeeVoteImpl
Definition: FeeVoteImpl.cpp:86
ripple::STValidation
Definition: STValidation.h:43
ripple::Fees::increment
XRPAmount increment
Definition: ReadView.h:52
ripple::ttFEE
@ ttFEE
Definition: TxFormats.h:60
ripple::base_uint< 256 >
ripple::detail::VotableValue::mCurrent
const value_type mCurrent
Definition: FeeVoteImpl.cpp:35
ripple::Fees
Reflects the fee settings for a particular ledger.
Definition: ReadView.h:47
ripple::detail::VotableValue::value_type
XRPAmount value_type
Definition: FeeVoteImpl.cpp:34
ripple::FeeVoteImpl::journal_
const beast::Journal journal_
Definition: FeeVoteImpl.cpp:90
ripple::XRPAmount::value_type
std::int64_t value_type
Definition: XRPAmount.h:53
ripple::detail::VotableValue::mTarget
const value_type mTarget
Definition: FeeVoteImpl.cpp:36
ripple::FeeVote::Setup::account_reserve
XRPAmount account_reserve
The account reserve requirement in drops.
Definition: FeeVote.h:49
ripple::detail::VotableValue
Definition: FeeVoteImpl.cpp:31
ripple::set
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:276
ripple::sfLedgerSequence
const SF_U32 sfLedgerSequence(access, STI_UINT32, 6, "LedgerSequence")
Definition: SField.h:357
beast::Journal::info
Stream info() const
Definition: Journal.h:321
ripple::sfReferenceFeeUnits
const SF_U32 sfReferenceFeeUnits(access, STI_UINT32, 30, "ReferenceFeeUnits")
Definition: SField.h:382
ripple::STTx
Definition: STTx.h:42
ripple::FeeVoteImpl::FeeVoteImpl
FeeVoteImpl(Setup const &setup, beast::Journal journal)
Definition: FeeVoteImpl.cpp:107
ripple::FeeVoteImpl::target_
Setup target_
Definition: FeeVoteImpl.cpp:89
ripple::ValStatus::current
@ current
This was a new validation and was added.
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
std::uint64_t
ripple::feeunit::TaggedFee
Definition: FeeUnits.h:70
std::map
STL class.
ripple::FeeVote::Setup::reference_fee_units
static constexpr FeeUnit32 reference_fee_units
The cost of a reference transaction in fee units.
Definition: FeeVote.h:46
ripple::detail::VotableValue::mVoteMap
std::map< value_type, int > mVoteMap
Definition: FeeVoteImpl.cpp:37
std::min
T min(T... args)
ripple::Serializer
Definition: Serializer.h:39
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::detail::VotableValue::getVotes
value_type getVotes() const
Definition: FeeVoteImpl.cpp:64
ripple::Fees::accountReserve
XRPAmount accountReserve(std::size_t ownerCount) const
Returns the account reserve given the owner count, in drops.
Definition: ReadView.h:65
ripple::sfReserveIncrement
const SF_U32 sfReserveIncrement(access, STI_UINT32, 32, "ReserveIncrement")
Definition: SField.h:384
ripple::Serializer::peekData
Blob const & peekData() const
Definition: Serializer.h:166
std::max
T max(T... args)
ripple::sfBaseFee
const SF_U64 sfBaseFee(access, STI_UINT64, 5, "BaseFee")
Definition: SField.h:398
ripple::STObject::setFieldU64
void setFieldU64(SField const &field, std::uint64_t)
Definition: STObject.cpp:638
std::unique_ptr
STL class.
ripple::XRPAmount::dropsAs
boost::optional< Dest > dropsAs() const
Definition: XRPAmount.h:182
ripple::detail::VotableValue::addVote
void addVote(value_type vote)
Definition: FeeVoteImpl.cpp:48
std::numeric_limits
ripple::STObject::setFieldU32
void setFieldU32(SField const &field, std::uint32_t)
Definition: STObject.cpp:632
ripple::AccountID
base_uint< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Definition: AccountID.h:47
ripple::Fees::base
XRPAmount base
Definition: ReadView.h:49
ripple::FeeVoteImpl::doVoting
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.
Definition: FeeVoteImpl.cpp:147
ripple::XRPAmount
Definition: XRPAmount.h:46