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
97  std::shared_ptr<ReadView const> const& lastClosedLedger,
98  STValidation::FeeSettings& fees) override;
99 
100  void
101  doVoting(
102  std::shared_ptr<ReadView const> const& lastClosedLedger,
103  std::vector<STValidation::pointer> const& parentValidations,
104  std::shared_ptr<SHAMap> const& initialPosition) override;
105 };
106 
107 //--------------------------------------------------------------------------
108 
109 FeeVoteImpl::FeeVoteImpl(Setup const& setup, beast::Journal journal)
110  : target_(setup), journal_(journal)
111 {
112 }
113 
114 void
116  std::shared_ptr<ReadView const> const& lastClosedLedger,
118 {
119  if (lastClosedLedger->fees().base != target_.reference_fee)
120  {
121  JLOG(journal_.info())
122  << "Voting for base fee of " << target_.reference_fee;
123 
125  }
126 
127  if (lastClosedLedger->fees().accountReserve(0) != target_.account_reserve)
128  {
129  JLOG(journal_.info())
130  << "Voting for base reserve of " << target_.account_reserve;
131 
133  }
134 
135  if (lastClosedLedger->fees().increment != target_.owner_reserve)
136  {
137  JLOG(journal_.info())
138  << "Voting for reserve increment of " << target_.owner_reserve;
139 
141  }
142 }
143 
144 void
146  std::shared_ptr<ReadView const> const& lastClosedLedger,
148  std::shared_ptr<SHAMap> const& initialPosition)
149 {
150  // LCL must be flag ledger
151  assert((lastClosedLedger->info().seq % 256) == 0);
152 
153  detail::VotableValue baseFeeVote(
154  lastClosedLedger->fees().base, target_.reference_fee);
155 
156  detail::VotableValue baseReserveVote(
157  lastClosedLedger->fees().accountReserve(0), target_.account_reserve);
158 
159  detail::VotableValue incReserveVote(
160  lastClosedLedger->fees().increment, target_.owner_reserve);
161 
162  for (auto const& val : set)
163  {
164  if (val->isTrusted())
165  {
166  if (val->isFieldPresent(sfBaseFee))
167  {
168  using xrptype = XRPAmount::value_type;
169  auto const vote = val->getFieldU64(sfBaseFee);
170  if (vote <= std::numeric_limits<xrptype>::max() &&
171  isLegalAmount(XRPAmount{unsafe_cast<xrptype>(vote)}))
172  baseFeeVote.addVote(
173  XRPAmount{unsafe_cast<XRPAmount::value_type>(vote)});
174  else
175  // Invalid amounts will be treated as if they're
176  // not provided. Don't throw because this value is
177  // provided by an external entity.
178  baseFeeVote.noVote();
179  }
180  else
181  {
182  baseFeeVote.noVote();
183  }
184 
185  if (val->isFieldPresent(sfReserveBase))
186  {
187  baseReserveVote.addVote(
188  XRPAmount{val->getFieldU32(sfReserveBase)});
189  }
190  else
191  {
192  baseReserveVote.noVote();
193  }
194 
195  if (val->isFieldPresent(sfReserveIncrement))
196  {
197  incReserveVote.addVote(
198  XRPAmount{val->getFieldU32(sfReserveIncrement)});
199  }
200  else
201  {
202  incReserveVote.noVote();
203  }
204  }
205  }
206 
207  // choose our positions
208  // If any of the values are invalid, send the current values.
209  auto const baseFee = baseFeeVote.getVotes().dropsAs<std::uint64_t>(
210  lastClosedLedger->fees().base);
211  auto const baseReserve = baseReserveVote.getVotes().dropsAs<std::uint32_t>(
212  lastClosedLedger->fees().accountReserve(0));
213  auto const incReserve = incReserveVote.getVotes().dropsAs<std::uint32_t>(
214  lastClosedLedger->fees().increment);
215  constexpr FeeUnit32 feeUnits = Setup::reference_fee_units;
216  auto const seq = lastClosedLedger->info().seq + 1;
217 
218  // add transactions to our position
219  if ((baseFee != lastClosedLedger->fees().base) ||
220  (baseReserve != lastClosedLedger->fees().accountReserve(0)) ||
221  (incReserve != lastClosedLedger->fees().increment))
222  {
223  JLOG(journal_.warn()) << "We are voting for a fee change: " << baseFee
224  << "/" << baseReserve << "/" << incReserve;
225 
226  STTx feeTx(
227  ttFEE,
228  [seq, baseFee, baseReserve, incReserve, feeUnits](auto& obj) {
229  obj[sfAccount] = AccountID();
230  obj[sfLedgerSequence] = seq;
231  obj[sfBaseFee] = baseFee;
232  obj[sfReserveBase] = baseReserve;
233  obj[sfReserveIncrement] = incReserve;
234  obj[sfReferenceFeeUnits] = feeUnits.fee();
235  });
236 
237  uint256 txID = feeTx.getTransactionID();
238 
239  JLOG(journal_.warn()) << "Vote: " << txID;
240 
241  Serializer s;
242  feeTx.add(s);
243 
244  auto tItem = std::make_shared<SHAMapItem>(txID, s.peekData());
245 
246  if (!initialPosition->addGiveItem(tItem, true, false))
247  {
248  JLOG(journal_.warn()) << "Ledger already had fee change";
249  }
250  }
251 }
252 
253 //------------------------------------------------------------------------------
254 
256 setup_FeeVote(Section const& section)
257 {
258  FeeVote::Setup setup;
259  {
260  std::uint64_t temp;
261  if (set(temp, "reference_fee", section) &&
263  setup.reference_fee = temp;
264  }
265  {
266  std::uint32_t temp;
267  if (set(temp, "account_reserve", section))
268  setup.account_reserve = temp;
269  if (set(temp, "owner_reserve", section))
270  setup.owner_reserve = temp;
271  }
272  return setup;
273 }
274 
277 {
278  return std::make_unique<FeeVoteImpl>(setup, journal);
279 }
280 
281 } // namespace ripple
ripple::setup_FeeVote
FeeVote::Setup setup_FeeVote(Section const &section)
Build FeeVote::Setup from a config section.
Definition: FeeVoteImpl.cpp:256
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
ripple::FeeVoteImpl::doValidation
void doValidation(std::shared_ptr< ReadView const > const &lastClosedLedger, STValidation::FeeSettings &fees) override
Add local fee preference to validation.
Definition: FeeVoteImpl.cpp:115
ripple::STValidation::FeeSettings::reserveBase
boost::optional< XRPAmount > reserveBase
Definition: STValidation.h:103
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:276
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:474
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::FeeVoteImpl::doVoting
void doVoting(std::shared_ptr< ReadView const > const &lastClosedLedger, std::vector< STValidation::pointer > const &parentValidations, std::shared_ptr< SHAMap > const &initialPosition) override
Cast our local vote on the fee.
Definition: FeeVoteImpl.cpp:145
ripple::ttFEE
@ ttFEE
Definition: TxFormats.h:60
ripple::base_uint< 256 >
ripple::detail::VotableValue::mCurrent
const value_type mCurrent
Definition: FeeVoteImpl.cpp:35
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:109
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:43
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::STValidation::FeeSettings::baseFee
boost::optional< XRPAmount > baseFee
Definition: STValidation.h:102
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:202
std::max
T max(T... args)
ripple::STValidation::FeeSettings::reserveIncrement
boost::optional< XRPAmount > reserveIncrement
Definition: STValidation.h:104
ripple::sfBaseFee
const SF_U64 sfBaseFee(access, STI_UINT64, 5, "BaseFee")
Definition: SField.h:398
std::unique_ptr
STL class.
ripple::XRPAmount::dropsAs
boost::optional< Dest > dropsAs() const
Definition: XRPAmount.h:182
ripple::STValidation::FeeSettings
Fees to set when issuing a new validation.
Definition: STValidation.h:99
ripple::detail::VotableValue::addVote
void addVote(value_type vote)
Definition: FeeVoteImpl.cpp:48
std::numeric_limits
ripple::AccountID
base_uint< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Definition: AccountID.h:47
ripple::XRPAmount
Definition: XRPAmount.h:46