rippled
STAmount.h
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 #ifndef RIPPLE_PROTOCOL_STAMOUNT_H_INCLUDED
21 #define RIPPLE_PROTOCOL_STAMOUNT_H_INCLUDED
22 
23 #include <ripple/basics/CountedObject.h>
24 #include <ripple/basics/IOUAmount.h>
25 #include <ripple/basics/LocalValue.h>
26 #include <ripple/basics/Number.h>
27 #include <ripple/basics/XRPAmount.h>
28 #include <ripple/protocol/Issue.h>
29 #include <ripple/protocol/SField.h>
30 #include <ripple/protocol/STBase.h>
31 #include <ripple/protocol/Serializer.h>
32 #include <ripple/protocol/json_get_or_throw.h>
33 
34 namespace ripple {
35 
36 // Internal form:
37 // 1: If amount is zero, then value is zero and offset is -100
38 // 2: Otherwise:
39 // legal offset range is -96 to +80 inclusive
40 // value range is 10^15 to (10^16 - 1) inclusive
41 // amount = value * [10 ^ offset]
42 
43 // Wire form:
44 // High 8 bits are (offset+142), legal range is, 80 to 22 inclusive
45 // Low 56 bits are value, legal range is 10^15 to (10^16 - 1) inclusive
46 class STAmount final : public STBase, public CountedObject<STAmount>
47 {
48 public:
50  using exponent_type = int;
52 
53 private:
57  bool mIsNative; // A shorthand for isXRP(mIssue).
59 
60 public:
62 
63  static const int cMinOffset = -96;
64  static const int cMaxOffset = 80;
65 
66  // Maximum native value supported by the code
67  static const std::uint64_t cMinValue = 1000000000000000ull;
68  static const std::uint64_t cMaxValue = 9999999999999999ull;
69  static const std::uint64_t cMaxNative = 9000000000000000000ull;
70 
71  // Max native value on network.
72  static const std::uint64_t cMaxNativeN = 100000000000000000ull;
73  static const std::uint64_t cNotNative = 0x8000000000000000ull;
74  static const std::uint64_t cPosNative = 0x4000000000000000ull;
75 
76  static std::uint64_t const uRateOne;
77 
78  //--------------------------------------------------------------------------
79  STAmount(SerialIter& sit, SField const& name);
80 
81  struct unchecked
82  {
83  explicit unchecked() = default;
84  };
85 
86  // Do not call canonicalize
87  STAmount(
88  SField const& name,
89  Issue const& issue,
92  bool native,
93  bool negative,
94  unchecked);
95 
96  STAmount(
97  Issue const& issue,
100  bool native,
101  bool negative,
102  unchecked);
103 
104  // Call canonicalize
105  STAmount(
106  SField const& name,
107  Issue const& issue,
110  bool native,
111  bool negative);
112 
113  STAmount(SField const& name, std::int64_t mantissa);
114 
115  STAmount(
116  SField const& name,
118  bool negative = false);
119 
120  STAmount(
121  SField const& name,
122  Issue const& issue,
124  int exponent = 0,
125  bool negative = false);
126 
127  explicit STAmount(std::uint64_t mantissa = 0, bool negative = false);
128 
129  explicit STAmount(SField const& name, STAmount const& amt);
130 
131  STAmount(
132  Issue const& issue,
134  int exponent = 0,
135  bool negative = false);
136 
137  // VFALCO Is this needed when we have the previous signature?
138  STAmount(
139  Issue const& issue,
141  int exponent = 0,
142  bool negative = false);
143 
144  STAmount(Issue const& issue, std::int64_t mantissa, int exponent = 0);
145 
146  STAmount(Issue const& issue, int mantissa, int exponent = 0);
147 
148  // Legacy support for new-style amounts
149  STAmount(IOUAmount const& amount, Issue const& issue);
150  STAmount(XRPAmount const& amount);
151  operator Number() const;
152 
153  //--------------------------------------------------------------------------
154  //
155  // Observers
156  //
157  //--------------------------------------------------------------------------
158 
159  int
160  exponent() const noexcept;
161 
162  bool
163  native() const noexcept;
164 
165  bool
166  negative() const noexcept;
167 
168  std::uint64_t
169  mantissa() const noexcept;
170 
171  Issue const&
172  issue() const;
173 
174  // These three are deprecated
175  Currency const&
176  getCurrency() const;
177 
178  AccountID const&
179  getIssuer() const;
180 
181  int
182  signum() const noexcept;
183 
185  STAmount
186  zeroed() const;
187 
188  void
189  setJson(Json::Value&) const;
190 
191  STAmount const&
192  value() const noexcept;
193 
194  //--------------------------------------------------------------------------
195  //
196  // Operators
197  //
198  //--------------------------------------------------------------------------
199 
200  explicit operator bool() const noexcept;
201 
202  STAmount&
203  operator+=(STAmount const&);
204  STAmount&
205  operator-=(STAmount const&);
206 
207  STAmount& operator=(beast::Zero);
208 
209  STAmount&
210  operator=(XRPAmount const& amount);
211 
212  //--------------------------------------------------------------------------
213  //
214  // Modification
215  //
216  //--------------------------------------------------------------------------
217 
218  void
219  negate();
220 
221  void
222  clear();
223 
224  // Zero while copying currency and issuer.
225  void
226  clear(STAmount const& saTmpl);
227 
228  void
229  clear(Issue const& issue);
230 
231  void
232  setIssuer(AccountID const& uIssuer);
233 
235  void
236  setIssue(Issue const& issue);
237 
238  //--------------------------------------------------------------------------
239  //
240  // STBase
241  //
242  //--------------------------------------------------------------------------
243 
245  getSType() const override;
246 
247  std::string
248  getFullText() const override;
249 
250  std::string
251  getText() const override;
252 
253  Json::Value getJson(JsonOptions) const override;
254 
255  void
256  add(Serializer& s) const override;
257 
258  bool
259  isEquivalent(const STBase& t) const override;
260 
261  bool
262  isDefault() const override;
263 
264  XRPAmount
265  xrp() const;
266  IOUAmount
267  iou() const;
268 
269 private:
270  static std::unique_ptr<STAmount>
271  construct(SerialIter&, SField const& name);
272 
273  void
274  set(std::int64_t v);
275  void
276  canonicalize();
277 
278  STBase*
279  copy(std::size_t n, void* buf) const override;
280  STBase*
281  move(std::size_t n, void* buf) override;
282 
283  STAmount&
284  operator=(IOUAmount const& iou);
285 
286  friend class detail::STVar;
287 
288  friend STAmount
289  operator+(STAmount const& v1, STAmount const& v2);
290 };
291 
292 //------------------------------------------------------------------------------
293 //
294 // Creation
295 //
296 //------------------------------------------------------------------------------
297 
298 // VFALCO TODO The parameter type should be Quality not uint64_t
299 STAmount
300 amountFromQuality(std::uint64_t rate);
301 
302 STAmount
303 amountFromString(Issue const& issue, std::string const& amount);
304 
305 STAmount
306 amountFromJson(SField const& name, Json::Value const& v);
307 
308 bool
309 amountFromJsonNoThrow(STAmount& result, Json::Value const& jvSource);
310 
311 // IOUAmount and XRPAmount define toSTAmount, defining this
312 // trivial conversion here makes writing generic code easier
313 inline STAmount const&
315 {
316  return a;
317 }
318 
319 //------------------------------------------------------------------------------
320 //
321 // Observers
322 //
323 //------------------------------------------------------------------------------
324 
325 inline int
326 STAmount::exponent() const noexcept
327 {
328  return mOffset;
329 }
330 
331 inline bool
332 STAmount::native() const noexcept
333 {
334  return mIsNative;
335 }
336 
337 inline bool
338 STAmount::negative() const noexcept
339 {
340  return mIsNegative;
341 }
342 
343 inline std::uint64_t
344 STAmount::mantissa() const noexcept
345 {
346  return mValue;
347 }
348 
349 inline Issue const&
351 {
352  return mIssue;
353 }
354 
355 inline Currency const&
357 {
358  return mIssue.currency;
359 }
360 
361 inline AccountID const&
363 {
364  return mIssue.account;
365 }
366 
367 inline int
368 STAmount::signum() const noexcept
369 {
370  return mValue ? (mIsNegative ? -1 : 1) : 0;
371 }
372 
373 inline STAmount
375 {
376  return STAmount(mIssue);
377 }
378 
379 inline STAmount::operator bool() const noexcept
380 {
381  return *this != beast::zero;
382 }
383 
384 inline STAmount::operator Number() const
385 {
386  if (mIsNative)
387  return xrp();
388  return iou();
389 }
390 
392 {
393  clear();
394  return *this;
395 }
396 
397 inline STAmount&
399 {
400  *this = STAmount(amount);
401  return *this;
402 }
403 
404 inline void
406 {
407  if (*this != beast::zero)
409 }
410 
411 inline void
413 {
414  // The -100 is used to allow 0 to sort less than a small positive values
415  // which have a negative exponent.
416  mOffset = mIsNative ? 0 : -100;
417  mValue = 0;
418  mIsNegative = false;
419 }
420 
421 // Zero while copying currency and issuer.
422 inline void
423 STAmount::clear(STAmount const& saTmpl)
424 {
425  clear(saTmpl.mIssue);
426 }
427 
428 inline void
430 {
431  setIssue(issue);
432  clear();
433 }
434 
435 inline void
437 {
438  mIssue.account = uIssuer;
439  setIssue(mIssue);
440 }
441 
442 inline STAmount const&
443 STAmount::value() const noexcept
444 {
445  return *this;
446 }
447 
448 inline bool
450 {
451  return !value.native() || (value.mantissa() <= STAmount::cMaxNativeN);
452 }
453 
454 //------------------------------------------------------------------------------
455 //
456 // Operators
457 //
458 //------------------------------------------------------------------------------
459 
460 bool
461 operator==(STAmount const& lhs, STAmount const& rhs);
462 bool
463 operator<(STAmount const& lhs, STAmount const& rhs);
464 
465 inline bool
466 operator!=(STAmount const& lhs, STAmount const& rhs)
467 {
468  return !(lhs == rhs);
469 }
470 
471 inline bool
472 operator>(STAmount const& lhs, STAmount const& rhs)
473 {
474  return rhs < lhs;
475 }
476 
477 inline bool
478 operator<=(STAmount const& lhs, STAmount const& rhs)
479 {
480  return !(rhs < lhs);
481 }
482 
483 inline bool
484 operator>=(STAmount const& lhs, STAmount const& rhs)
485 {
486  return !(lhs < rhs);
487 }
488 
489 STAmount
490 operator-(STAmount const& value);
491 
492 //------------------------------------------------------------------------------
493 //
494 // Arithmetic
495 //
496 //------------------------------------------------------------------------------
497 
498 STAmount
499 operator+(STAmount const& v1, STAmount const& v2);
500 STAmount
501 operator-(STAmount const& v1, STAmount const& v2);
502 
503 STAmount
504 divide(STAmount const& v1, STAmount const& v2, Issue const& issue);
505 
506 STAmount
507 multiply(STAmount const& v1, STAmount const& v2, Issue const& issue);
508 
509 // multiply rounding result in specified direction
510 STAmount
511 mulRound(
512  STAmount const& v1,
513  STAmount const& v2,
514  Issue const& issue,
515  bool roundUp);
516 
517 // multiply following the rounding directions more precisely.
518 STAmount
520  STAmount const& v1,
521  STAmount const& v2,
522  Issue const& issue,
523  bool roundUp);
524 
525 // divide rounding result in specified direction
526 STAmount
527 divRound(
528  STAmount const& v1,
529  STAmount const& v2,
530  Issue const& issue,
531  bool roundUp);
532 
533 // divide following the rounding directions more precisely.
534 STAmount
536  STAmount const& v1,
537  STAmount const& v2,
538  Issue const& issue,
539  bool roundUp);
540 
541 // Someone is offering X for Y, what is the rate?
542 // Rate: smaller is better, the taker wants the most out: in/out
543 // VFALCO TODO Return a Quality object
545 getRate(STAmount const& offerOut, STAmount const& offerIn);
546 
547 //------------------------------------------------------------------------------
548 
549 inline bool
550 isXRP(STAmount const& amount)
551 {
552  return isXRP(amount.issue().currency);
553 }
554 
555 // Since `canonicalize` does not have access to a ledger, this is needed to put
556 // the low-level routine stAmountCanonicalize on an amendment switch. Only
557 // transactions need to use this switchover. Outside of a transaction it's safe
558 // to unconditionally use the new behavior.
559 
560 bool
562 
563 void
565 
570 {
571 public:
572  explicit STAmountSO(bool v) : saved_(getSTAmountCanonicalizeSwitchover())
573  {
575  }
576 
578  {
580  }
581 
582 private:
583  bool saved_;
584 };
585 
586 } // namespace ripple
587 
588 //------------------------------------------------------------------------------
589 namespace Json {
590 template <>
591 inline ripple::STAmount
592 getOrThrow(Json::Value const& v, ripple::SField const& field)
593 {
594  using namespace ripple;
595  Json::StaticString const& key = field.getJsonName();
596  if (!v.isMember(key))
597  Throw<JsonMissingKeyError>(key);
598  Json::Value const& inner = v[key];
599  return amountFromJson(field, inner);
600 }
601 } // namespace Json
602 #endif
ripple::STAmount::mIsNative
bool mIsNative
Definition: STAmount.h:57
ripple::STAmount::move
STBase * move(std::size_t n, void *buf) override
Definition: STAmount.cpp:334
ripple::STAmount::negate
void negate()
Definition: STAmount.h:405
ripple::STAmount::copy
STBase * copy(std::size_t n, void *buf) const override
Definition: STAmount.cpp:328
ripple::amountFromJsonNoThrow
bool amountFromJsonNoThrow(STAmount &result, Json::Value const &jvSource)
Definition: STAmount.cpp:1032
ripple::STAmountSO
RAII class to set and restore the STAmount canonicalize switchover.
Definition: STAmount.h:569
ripple::CountedObject
Tracks the number of instances of an object.
Definition: CountedObject.h:124
ripple::Issue
A currency issued by an account.
Definition: Issue.h:35
ripple::STAmount::cMinValue
static const std::uint64_t cMinValue
Definition: STAmount.h:67
ripple::STAmount::set
void set(std::int64_t v)
Definition: STAmount.cpp:833
ripple::JsonOptions
JsonOptions
Definition: STBase.h:34
ripple::STAmount::clear
void clear()
Definition: STAmount.h:412
ripple::STAmount::issue
Issue const & issue() const
Definition: STAmount.h:350
ripple::STAmount::mantissa
std::uint64_t mantissa() const noexcept
Definition: STAmount.h:344
ripple::STAmountSO::~STAmountSO
~STAmountSO()
Definition: STAmount.h:577
std::pair
ripple::mulRoundStrict
STAmount mulRoundStrict(STAmount const &v1, STAmount const &v2, Issue const &issue, bool roundUp)
Definition: STAmount.cpp:1519
ripple::STAmount::getText
std::string getText() const override
Definition: STAmount.cpp:569
ripple::STAmount::getJson
Json::Value getJson(JsonOptions) const override
Definition: STAmount.cpp:653
ripple::SerializedTypeID
SerializedTypeID
Definition: SField.h:104
ripple::operator-
Number operator-(Number const &x, Number const &y)
Definition: Number.h:277
ripple::STAmount::cMaxNative
static const std::uint64_t cMaxNative
Definition: STAmount.h:69
ripple::STAmount::mValue
mantissa_type mValue
Definition: STAmount.h:55
ripple::Issue::currency
Currency currency
Definition: Issue.h:38
ripple::STAmount::signum
int signum() const noexcept
Definition: STAmount.h:368
ripple::STAmount::cMinOffset
static const int cMinOffset
Definition: STAmount.h:63
ripple::isLegalNet
bool isLegalNet(STAmount const &value)
Definition: STAmount.h:449
ripple::STAmount::cNotNative
static const std::uint64_t cNotNative
Definition: STAmount.h:73
ripple::IOUAmount
Floating point representation of amounts with high dynamic range.
Definition: IOUAmount.h:43
ripple::STAmount::operator=
STAmount & operator=(beast::Zero)
Definition: STAmount.h:391
ripple::STAmount::setIssuer
void setIssuer(AccountID const &uIssuer)
Definition: STAmount.h:436
ripple::STAmount::zeroed
STAmount zeroed() const
Returns a zero value with the same issuer and currency.
Definition: STAmount.h:374
ripple::STAmount::iou
IOUAmount iou() const
Definition: STAmount.cpp:360
ripple::STAmount::operator+
friend STAmount operator+(STAmount const &v1, STAmount const &v2)
Definition: STAmount.cpp:408
ripple::STAmount::xrp
XRPAmount xrp() const
Definition: STAmount.cpp:345
ripple::mulRound
STAmount mulRound(STAmount const &v1, STAmount const &v2, Issue const &issue, bool roundUp)
Definition: STAmount.cpp:1508
ripple::STAmount::getIssuer
AccountID const & getIssuer() const
Definition: STAmount.h:362
ripple::getRate
std::uint64_t getRate(STAmount const &offerOut, STAmount const &offerIn)
Definition: STAmount.cpp:506
ripple::divide
STAmount divide(STAmount const &amount, Rate const &rate)
Definition: Rate2.cpp:86
ripple::base_uint< 160, detail::CurrencyTag >
ripple::STAmount::getFullText
std::string getFullText() const override
Definition: STAmount.cpp:559
ripple::STAmount::exponent
int exponent() const noexcept
Definition: STAmount.h:326
Json
JSON (JavaScript Object Notation).
Definition: DeliverMax.h:28
ripple::operator<=
bool operator<=(STAmount const &lhs, STAmount const &rhs)
Definition: STAmount.h:478
ripple::STAmount::mIssue
Issue mIssue
Definition: STAmount.h:54
ripple::STAmount::setJson
void setJson(Json::Value &) const
Definition: STAmount.cpp:528
ripple::Number
Definition: Number.h:36
ripple::STAmount::STAmount
STAmount(SerialIter &sit, SField const &name)
Definition: STAmount.cpp:88
ripple::operator>
bool operator>(STAmount const &lhs, STAmount const &rhs)
Definition: STAmount.h:472
ripple::setSTAmountCanonicalizeSwitchover
void setSTAmountCanonicalizeSwitchover(bool v)
Definition: STAmount.cpp:55
ripple::operator<
bool operator<(CanonicalTXSet::Key const &lhs, CanonicalTXSet::Key const &rhs)
Definition: CanonicalTXSet.cpp:25
ripple::divRound
STAmount divRound(STAmount const &num, STAmount const &den, Issue const &issue, bool roundUp)
Definition: STAmount.cpp:1614
ripple::STAmount::unchecked::unchecked
unchecked()=default
ripple::toSTAmount
STAmount toSTAmount(IOUAmount const &iou, Issue const &iss)
Definition: AmountConversions.h:30
ripple::divRoundStrict
STAmount divRoundStrict(STAmount const &num, STAmount const &den, Issue const &issue, bool roundUp)
Definition: STAmount.cpp:1624
ripple::STAmount::value
STAmount const & value() const noexcept
Definition: STAmount.h:443
ripple::operator>=
bool operator>=(STAmount const &lhs, STAmount const &rhs)
Definition: STAmount.h:484
beast::Zero
Zero allows classes to offer efficient comparisons to zero.
Definition: Zero.h:42
ripple::STAmount
Definition: STAmount.h:46
ripple::getSTAmountCanonicalizeSwitchover
bool getSTAmountCanonicalizeSwitchover()
Definition: STAmount.cpp:49
ripple::amountFromJson
STAmount amountFromJson(SField const &name, Json::Value const &v)
Definition: STAmount.cpp:927
ripple::isXRP
bool isXRP(AccountID const &c)
Definition: AccountID.h:91
ripple::SerialIter
Definition: Serializer.h:311
Json::Value::isMember
bool isMember(const char *key) const
Return true if the object has a member named key.
Definition: json_value.cpp:932
std::uint64_t
ripple::STAmount::setIssue
void setIssue(Issue const &issue)
Set the Issue for this amount and update mIsNative.
Definition: STAmount.cpp:490
ripple::STAmount::construct
static std::unique_ptr< STAmount > construct(SerialIter &, SField const &name)
Definition: STAmount.cpp:322
ripple::amountFromQuality
STAmount amountFromQuality(std::uint64_t rate)
Definition: STAmount.cpp:850
ripple::multiply
STAmount multiply(STAmount const &amount, Rate const &rate)
Definition: Rate2.cpp:47
ripple::Serializer
Definition: Serializer.h:40
ripple::STAmount::isEquivalent
bool isEquivalent(const STBase &t) const override
Definition: STAmount.cpp:692
ripple::STAmount::native
bool native() const noexcept
Definition: STAmount.h:332
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::STAmount::mIsNegative
bool mIsNegative
Definition: STAmount.h:58
ripple::amountFromString
STAmount amountFromString(Issue const &issue, std::string const &amount)
Definition: STAmount.cpp:862
ripple::STAmount::isDefault
bool isDefault() const override
Definition: STAmount.cpp:699
ripple::STAmount::unchecked
Definition: STAmount.h:81
ripple::SField
Identifies fields.
Definition: SField.h:139
ripple::STBase
A type which can be exported to a well known binary format.
Definition: STBase.h:66
ripple::STBase::operator!=
bool operator!=(const STBase &t) const
Definition: STBase.cpp:51
Json::StaticString
Lightweight wrapper to tag static string.
Definition: json_value.h:60
std
STL namespace.
ripple::STAmount::canonicalize
void canonicalize()
Definition: STAmount.cpp:723
ripple::STAmount::add
void add(Serializer &s) const override
Definition: STAmount.cpp:661
ripple::STAmount::negative
bool negative() const noexcept
Definition: STAmount.h:338
ripple::STBase::operator==
bool operator==(const STBase &t) const
Definition: STBase.cpp:45
ripple::STAmount::exponent_type
int exponent_type
Definition: STAmount.h:50
ripple::STAmount::cMaxNativeN
static const std::uint64_t cMaxNativeN
Definition: STAmount.h:72
ripple::STAmount::cMaxOffset
static const int cMaxOffset
Definition: STAmount.h:64
ripple::STAmount::getCurrency
Currency const & getCurrency() const
Definition: STAmount.h:356
ripple::STAmount::mOffset
exponent_type mOffset
Definition: STAmount.h:56
ripple::STAmountSO::saved_
bool saved_
Definition: STAmount.h:583
ripple::STAmount::cPosNative
static const std::uint64_t cPosNative
Definition: STAmount.h:74
ripple::STAmount::uRateOne
static const std::uint64_t uRateOne
Definition: STAmount.h:76
ripple::STAmount::getSType
SerializedTypeID getSType() const override
Definition: STAmount.cpp:553
ripple::Issue::account
AccountID account
Definition: Issue.h:39
ripple::STAmount::cMaxValue
static const std::uint64_t cMaxValue
Definition: STAmount.h:68
Json::Value
Represents a JSON value.
Definition: json_value.h:145
ripple::STAmountSO::STAmountSO
STAmountSO(bool v)
Definition: STAmount.h:572
ripple::XRPAmount
Definition: XRPAmount.h:46
beast
Definition: base_uint.h:641