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