rippled
Loading...
Searching...
No Matches
STAmount.h
1#ifndef XRPL_PROTOCOL_STAMOUNT_H_INCLUDED
2#define XRPL_PROTOCOL_STAMOUNT_H_INCLUDED
3
4#include <xrpl/basics/CountedObject.h>
5#include <xrpl/basics/LocalValue.h>
6#include <xrpl/basics/Number.h>
7#include <xrpl/beast/utility/instrumentation.h>
8#include <xrpl/protocol/Asset.h>
9#include <xrpl/protocol/IOUAmount.h>
10#include <xrpl/protocol/Issue.h>
11#include <xrpl/protocol/MPTAmount.h>
12#include <xrpl/protocol/SField.h>
13#include <xrpl/protocol/STBase.h>
14#include <xrpl/protocol/Serializer.h>
15#include <xrpl/protocol/XRPAmount.h>
16#include <xrpl/protocol/json_get_or_throw.h>
17
18namespace xrpl {
19
20// Internal form:
21// 1: If amount is zero, then value is zero and offset is -100
22// 2: Otherwise:
23// legal offset range is -96 to +80 inclusive
24// value range is 10^15 to (10^16 - 1) inclusive
25// amount = value * [10 ^ offset]
26
27// Wire form:
28// High 8 bits are (offset+142), legal range is, 80 to 22 inclusive
29// Low 56 bits are value, legal range is 10^15 to (10^16 - 1) inclusive
30class STAmount final : public STBase, public CountedObject<STAmount>
31{
32public:
34 using exponent_type = int;
36
37private:
42
43public:
45
46 static int const cMinOffset = -96;
47 static int const cMaxOffset = 80;
48
49 // Maximum native value supported by the code
50 constexpr static std::uint64_t cMinValue = 1'000'000'000'000'000ull;
51 static_assert(isPowerOfTen(cMinValue));
52 constexpr static std::uint64_t cMaxValue = cMinValue * 10 - 1;
53 static_assert(cMaxValue == 9'999'999'999'999'999ull);
54 constexpr static std::uint64_t cMaxNative = 9'000'000'000'000'000'000ull;
55
56 // Max native value on network.
57 constexpr static std::uint64_t cMaxNativeN = 100'000'000'000'000'000ull;
58 constexpr static std::uint64_t cIssuedCurrency = 0x8'000'000'000'000'000ull;
59 constexpr static std::uint64_t cPositive = 0x4'000'000'000'000'000ull;
60 constexpr static std::uint64_t cMPToken = 0x2'000'000'000'000'000ull;
61 constexpr static std::uint64_t cValueMask = ~(cPositive | cMPToken);
62
63 static std::uint64_t const uRateOne;
64
65 //--------------------------------------------------------------------------
66 STAmount(SerialIter& sit, SField const& name);
67
68 struct unchecked
69 {
70 explicit unchecked() = default;
71 };
72
73 // Do not call canonicalize
74 template <AssetType A>
76 SField const& name,
77 A const& asset,
80 bool negative,
81 unchecked);
82
83 template <AssetType A>
85 A const& asset,
88 bool negative,
89 unchecked);
90
91 // Call canonicalize
92 template <AssetType A>
94 SField const& name,
95 A const& asset,
98 bool negative = false);
99
100 STAmount(SField const& name, std::int64_t mantissa);
101
102 STAmount(
103 SField const& name,
105 bool negative = false);
106
107 explicit STAmount(std::uint64_t mantissa = 0, bool negative = false);
108
109 explicit STAmount(SField const& name, STAmount const& amt);
110
111 template <AssetType A>
113 A const& asset,
115 int exponent = 0,
116 bool negative = false)
117 : mAsset(asset)
121 {
122 canonicalize();
123 }
124
125 // VFALCO Is this needed when we have the previous signature?
126 template <AssetType A>
127 STAmount(
128 A const& asset,
130 int exponent = 0,
131 bool negative = false);
132
133 template <AssetType A>
134 STAmount(A const& asset, std::int64_t mantissa, int exponent = 0);
135
136 template <AssetType A>
137 STAmount(A const& asset, int mantissa, int exponent = 0);
138
139 template <AssetType A>
140 STAmount(A const& asset, Number const& number)
141 : STAmount(asset, number.mantissa(), number.exponent())
142 {
143 }
144
145 // Legacy support for new-style amounts
146 STAmount(IOUAmount const& amount, Issue const& issue);
147 STAmount(XRPAmount const& amount);
148 STAmount(MPTAmount const& amount, MPTIssue const& mptIssue);
149 operator Number() const;
150
151 //--------------------------------------------------------------------------
152 //
153 // Observers
154 //
155 //--------------------------------------------------------------------------
156
157 int
158 exponent() const noexcept;
159
160 bool
161 integral() const noexcept;
162
163 bool
164 native() const noexcept;
165
166 template <ValidIssueType TIss>
167 constexpr bool
168 holds() const noexcept;
169
170 bool
171 negative() const noexcept;
172
173 std::uint64_t
174 mantissa() const noexcept;
175
176 Asset const&
177 asset() const;
178
179 template <ValidIssueType TIss>
180 constexpr TIss const&
181 get() const;
182
183 Issue const&
184 issue() const;
185
186 // These three are deprecated
187 Currency const&
188 getCurrency() const;
189
190 AccountID const&
191 getIssuer() const;
192
193 int
194 signum() const noexcept;
195
198 zeroed() const;
199
200 void
201 setJson(Json::Value&) const;
202
203 STAmount const&
204 value() const noexcept;
205
206 //--------------------------------------------------------------------------
207 //
208 // Operators
209 //
210 //--------------------------------------------------------------------------
211
212 explicit
213 operator bool() const noexcept;
214
215 STAmount&
216 operator+=(STAmount const&);
217 STAmount&
218 operator-=(STAmount const&);
219
220 STAmount& operator=(beast::Zero);
221
222 STAmount&
223 operator=(XRPAmount const& amount);
224
225 STAmount&
226 operator=(Number const&);
227
228 //--------------------------------------------------------------------------
229 //
230 // Modification
231 //
232 //--------------------------------------------------------------------------
233
234 void
235 negate();
236
237 void
238 clear();
239
240 // Zero while copying currency and issuer.
241 void
242 clear(Asset const& asset);
243
244 void
245 setIssuer(AccountID const& uIssuer);
246
248 void
249 setIssue(Asset const& asset);
250
251 //--------------------------------------------------------------------------
252 //
253 // STBase
254 //
255 //--------------------------------------------------------------------------
256
258 getSType() const override;
259
260 std::string
261 getFullText() const override;
262
263 std::string
264 getText() const override;
265
266 Json::Value getJson(JsonOptions = JsonOptions::none) const override;
267
268 void
269 add(Serializer& s) const override;
270
271 bool
272 isEquivalent(STBase const& t) const override;
273
274 bool
275 isDefault() const override;
276
278 xrp() const;
280 iou() const;
282 mpt() const;
283
284private:
285 static std::unique_ptr<STAmount>
286 construct(SerialIter&, SField const& name);
287
288 void
289 set(std::int64_t v);
290 void
291 canonicalize();
292
293 STBase*
294 copy(std::size_t n, void* buf) const override;
295 STBase*
296 move(std::size_t n, void* buf) override;
297
298 STAmount&
299 operator=(IOUAmount const& iou);
300
301 friend class detail::STVar;
302
303 friend STAmount
304 operator+(STAmount const& v1, STAmount const& v2);
305};
306
307template <AssetType A>
309 SField const& name,
310 A const& asset,
313 bool negative,
314 unchecked)
315 : STBase(name)
316 , mAsset(asset)
320{
321}
322
323template <AssetType A>
333
334template <AssetType A>
336 SField const& name,
337 A const& asset,
338 std::uint64_t mantissa,
339 int exponent,
340 bool negative)
341 : STBase(name)
342 , mAsset(asset)
343 , mValue(mantissa)
344 , mOffset(exponent)
345 , mIsNegative(negative)
346{
347 // mValue is uint64, but needs to fit in the range of int64
348 XRPL_ASSERT(
350 "xrpl::STAmount::STAmount(SField, A, std::uint64_t, int, bool) : "
351 "maximum mantissa input");
352 canonicalize();
353}
354
355template <AssetType A>
356STAmount::STAmount(A const& asset, std::int64_t mantissa, int exponent)
357 : mAsset(asset), mOffset(exponent)
358{
359 set(mantissa);
360 canonicalize();
361}
362
363template <AssetType A>
365 A const& asset,
366 std::uint32_t mantissa,
367 int exponent,
368 bool negative)
369 : STAmount(asset, safe_cast<std::uint64_t>(mantissa), exponent, negative)
370{
371}
372
373template <AssetType A>
374STAmount::STAmount(A const& asset, int mantissa, int exponent)
375 : STAmount(asset, safe_cast<std::int64_t>(mantissa), exponent)
376{
377}
378
379// Legacy support for new-style amounts
380inline STAmount::STAmount(IOUAmount const& amount, Issue const& issue)
381 : mAsset(issue)
382 , mOffset(amount.exponent())
383 , mIsNegative(amount < beast::zero)
384{
385 if (mIsNegative)
386 mValue = unsafe_cast<std::uint64_t>(-amount.mantissa());
387 else
388 mValue = unsafe_cast<std::uint64_t>(amount.mantissa());
389
390 canonicalize();
391}
392
393inline STAmount::STAmount(MPTAmount const& amount, MPTIssue const& mptIssue)
394 : mAsset(mptIssue), mOffset(0), mIsNegative(amount < beast::zero)
395{
396 if (mIsNegative)
397 mValue = unsafe_cast<std::uint64_t>(-amount.value());
398 else
399 mValue = unsafe_cast<std::uint64_t>(amount.value());
400
401 canonicalize();
402}
403
404//------------------------------------------------------------------------------
405//
406// Creation
407//
408//------------------------------------------------------------------------------
409
410// VFALCO TODO The parameter type should be Quality not uint64_t
413
415amountFromString(Asset const& asset, std::string const& amount);
416
418amountFromJson(SField const& name, Json::Value const& v);
419
420bool
421amountFromJsonNoThrow(STAmount& result, Json::Value const& jvSource);
422
423// IOUAmount and XRPAmount define toSTAmount, defining this
424// trivial conversion here makes writing generic code easier
425inline STAmount const&
427{
428 return a;
429}
430
431//------------------------------------------------------------------------------
432//
433// Observers
434//
435//------------------------------------------------------------------------------
436
437inline int
438STAmount::exponent() const noexcept
439{
440 return mOffset;
441}
442
443inline bool
444STAmount::integral() const noexcept
445{
446 return mAsset.integral();
447}
448
449inline bool
450STAmount::native() const noexcept
451{
452 return mAsset.native();
453}
454
455template <ValidIssueType TIss>
456constexpr bool
457STAmount::holds() const noexcept
458{
459 return mAsset.holds<TIss>();
460}
461
462inline bool
463STAmount::negative() const noexcept
464{
465 return mIsNegative;
466}
467
468inline std::uint64_t
469STAmount::mantissa() const noexcept
470{
471 return mValue;
472}
473
474inline Asset const&
476{
477 return mAsset;
478}
479
480template <ValidIssueType TIss>
481constexpr TIss const&
483{
484 return mAsset.get<TIss>();
485}
486
487inline Issue const&
489{
490 return get<Issue>();
491}
492
493inline Currency const&
495{
496 return mAsset.get<Issue>().currency;
497}
498
499inline AccountID const&
501{
502 return mAsset.getIssuer();
503}
504
505inline int
506STAmount::signum() const noexcept
507{
508 return mValue ? (mIsNegative ? -1 : 1) : 0;
509}
510
511inline STAmount
513{
514 return STAmount(mAsset);
515}
516
517inline STAmount::operator bool() const noexcept
518{
519 return *this != beast::zero;
520}
521
522inline STAmount::operator Number() const
523{
524 if (native())
525 return xrp();
526 if (mAsset.holds<MPTIssue>())
527 return mpt();
528 return iou();
529}
530
531inline STAmount&
533{
534 clear();
535 return *this;
536}
537
538inline STAmount&
540{
541 *this = STAmount(amount);
542 return *this;
543}
544
545inline STAmount&
547{
548 mIsNegative = number.mantissa() < 0;
549 mValue = mIsNegative ? -number.mantissa() : number.mantissa();
550 mOffset = number.exponent();
551 canonicalize();
552 return *this;
553}
554
555inline void
557{
558 if (*this != beast::zero)
560}
561
562inline void
564{
565 // The -100 is used to allow 0 to sort less than a small positive values
566 // which have a negative exponent.
567 mOffset = integral() ? 0 : -100;
568 mValue = 0;
569 mIsNegative = false;
570}
571
572inline void
574{
576 clear();
577}
578
579inline void
581{
582 mAsset.get<Issue>().account = uIssuer;
583}
584
585inline STAmount const&
586STAmount::value() const noexcept
587{
588 return *this;
589}
590
591inline bool
592isLegalNet(STAmount const& value)
593{
594 return !value.native() || (value.mantissa() <= STAmount::cMaxNativeN);
595}
596
597//------------------------------------------------------------------------------
598//
599// Operators
600//
601//------------------------------------------------------------------------------
602
603bool
604operator==(STAmount const& lhs, STAmount const& rhs);
605bool
606operator<(STAmount const& lhs, STAmount const& rhs);
607
608inline bool
609operator!=(STAmount const& lhs, STAmount const& rhs)
610{
611 return !(lhs == rhs);
612}
613
614inline bool
615operator>(STAmount const& lhs, STAmount const& rhs)
616{
617 return rhs < lhs;
618}
619
620inline bool
621operator<=(STAmount const& lhs, STAmount const& rhs)
622{
623 return !(rhs < lhs);
624}
625
626inline bool
627operator>=(STAmount const& lhs, STAmount const& rhs)
628{
629 return !(lhs < rhs);
630}
631
632STAmount
633operator-(STAmount const& value);
634
635//------------------------------------------------------------------------------
636//
637// Arithmetic
638//
639//------------------------------------------------------------------------------
640
641STAmount
642operator+(STAmount const& v1, STAmount const& v2);
643STAmount
644operator-(STAmount const& v1, STAmount const& v2);
645
646STAmount
647divide(STAmount const& v1, STAmount const& v2, Asset const& asset);
648
649STAmount
650multiply(STAmount const& v1, STAmount const& v2, Asset const& asset);
651
652// multiply rounding result in specified direction
653STAmount
655 STAmount const& v1,
656 STAmount const& v2,
657 Asset const& asset,
658 bool roundUp);
659
660// multiply following the rounding directions more precisely.
661STAmount
663 STAmount const& v1,
664 STAmount const& v2,
665 Asset const& asset,
666 bool roundUp);
667
668// divide rounding result in specified direction
669STAmount
671 STAmount const& v1,
672 STAmount const& v2,
673 Asset const& asset,
674 bool roundUp);
675
676// divide following the rounding directions more precisely.
677STAmount
679 STAmount const& v1,
680 STAmount const& v2,
681 Asset const& asset,
682 bool roundUp);
683
684// Someone is offering X for Y, what is the rate?
685// Rate: smaller is better, the taker wants the most out: in/out
686// VFALCO TODO Return a Quality object
688getRate(STAmount const& offerOut, STAmount const& offerIn);
689
702STAmount
704 STAmount const& value,
705 std::int32_t scale,
707
720template <AssetType A>
721Number
723 A const& asset,
724 Number const& value,
725 std::int32_t scale,
727{
728 NumberRoundModeGuard mg(rounding);
729 STAmount const ret{asset, value};
730 if (ret.integral())
731 return ret;
732 // Note that the ctor will round integral types (XRP, MPT) via canonicalize,
733 // so no extra work is needed for those.
734 return roundToScale(ret, scale);
735}
736
737//------------------------------------------------------------------------------
738
739inline bool
740isXRP(STAmount const& amount)
741{
742 return amount.native();
743}
744
745bool
746canAdd(STAmount const& amt1, STAmount const& amt2);
747
748bool
749canSubtract(STAmount const& amt1, STAmount const& amt2);
750
751} // namespace xrpl
752
753//------------------------------------------------------------------------------
754namespace Json {
755template <>
756inline xrpl::STAmount
757getOrThrow(Json::Value const& v, xrpl::SField const& field)
758{
759 using namespace xrpl;
760 Json::StaticString const& key = field.getJsonName();
761 if (!v.isMember(key))
762 Throw<JsonMissingKeyError>(key);
763 Json::Value const& inner = v[key];
764 return amountFromJson(field, inner);
765}
766} // namespace Json
767#endif
Lightweight wrapper to tag static string.
Definition json_value.h:45
Represents a JSON value.
Definition json_value.h:131
bool isMember(char const *key) const
Return true if the object has a member named key.
constexpr TIss const & get() const
AccountID const & getIssuer() const
Definition Asset.cpp:17
bool integral() const
Definition Asset.h:95
bool native() const
Definition Asset.h:82
constexpr bool holds() const
Definition Asset.h:133
Tracks the number of instances of an object.
Floating point representation of amounts with high dynamic range.
Definition IOUAmount.h:27
A currency issued by an account.
Definition Issue.h:14
static rounding_mode getround()
Definition Number.cpp:28
constexpr rep mantissa() const noexcept
Definition Number.h:209
constexpr int exponent() const noexcept
Definition Number.h:215
Identifies fields.
Definition SField.h:127
void set(std::int64_t v)
Definition STAmount.cpp:948
constexpr bool holds() const noexcept
Definition STAmount.h:457
Json::Value getJson(JsonOptions=JsonOptions::none) const override
Definition STAmount.cpp:751
constexpr TIss const & get() const
void setIssue(Asset const &asset)
Set the Issue for this amount.
Definition STAmount.cpp:428
std::string getFullText() const override
Definition STAmount.cpp:653
static constexpr std::uint64_t cMaxValue
Definition STAmount.h:52
Issue const & issue() const
Definition STAmount.h:488
static std::uint64_t const uRateOne
Definition STAmount.h:63
void add(Serializer &s) const override
Definition STAmount.cpp:759
void setIssuer(AccountID const &uIssuer)
Definition STAmount.h:580
void negate()
Definition STAmount.h:556
void canonicalize()
Definition STAmount.cpp:829
std::uint64_t mantissa() const noexcept
Definition STAmount.h:469
int signum() const noexcept
Definition STAmount.h:506
friend class detail::STVar
Definition STAmount.h:301
bool isEquivalent(STBase const &t) const override
Definition STAmount.cpp:798
STBase * copy(std::size_t n, void *buf) const override
Definition STAmount.cpp:247
exponent_type mOffset
Definition STAmount.h:40
static constexpr std::uint64_t cValueMask
Definition STAmount.h:61
std::string getText() const override
Definition STAmount.cpp:663
bool mIsNegative
Definition STAmount.h:41
void setJson(Json::Value &) const
Definition STAmount.cpp:623
SerializedTypeID getSType() const override
Definition STAmount.cpp:647
IOUAmount iou() const
Definition STAmount.cpp:280
bool negative() const noexcept
Definition STAmount.h:463
STAmount zeroed() const
Returns a zero value with the same issuer and currency.
Definition STAmount.h:512
static int const cMaxOffset
Definition STAmount.h:47
bool isDefault() const override
Definition STAmount.cpp:805
bool integral() const noexcept
Definition STAmount.h:444
mantissa_type mValue
Definition STAmount.h:39
STAmount & operator=(beast::Zero)
Definition STAmount.h:532
Currency const & getCurrency() const
Definition STAmount.h:494
static std::unique_ptr< STAmount > construct(SerialIter &, SField const &name)
Definition STAmount.cpp:241
static constexpr std::uint64_t cIssuedCurrency
Definition STAmount.h:58
bool native() const noexcept
Definition STAmount.h:450
static constexpr std::uint64_t cMinValue
Definition STAmount.h:50
Asset const & asset() const
Definition STAmount.h:475
static int const cMinOffset
Definition STAmount.h:46
static constexpr std::uint64_t cMaxNative
Definition STAmount.h:54
int exponent_type
Definition STAmount.h:34
STAmount(A const &asset, Number const &number)
Definition STAmount.h:140
MPTAmount mpt() const
Definition STAmount.cpp:295
static constexpr std::uint64_t cMPToken
Definition STAmount.h:60
int exponent() const noexcept
Definition STAmount.h:438
AccountID const & getIssuer() const
Definition STAmount.h:500
static constexpr std::uint64_t cMaxNativeN
Definition STAmount.h:57
STBase * move(std::size_t n, void *buf) override
Definition STAmount.cpp:253
XRPAmount xrp() const
Definition STAmount.cpp:264
static constexpr std::uint64_t cPositive
Definition STAmount.h:59
STAmount const & value() const noexcept
Definition STAmount.h:586
STAmount(SerialIter &sit, SField const &name)
Definition STAmount.cpp:101
STAmount(A const &asset, std::uint64_t mantissa=0, int exponent=0, bool negative=false)
Definition STAmount.h:112
A type which can be exported to a well known binary format.
Definition STBase.h:116
JSON (JavaScript Object Notation).
Definition json_errors.h:6
xrpl::AccountID getOrThrow(Json::Value const &v, xrpl::SField const &field)
Definition AccountID.h:112
STL namespace.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
STAmount divide(STAmount const &amount, Rate const &rate)
Definition Rate2.cpp:74
bool operator<(Slice const &lhs, Slice const &rhs) noexcept
Definition Slice.h:204
bool operator>=(STAmount const &lhs, STAmount const &rhs)
Definition STAmount.h:627
bool isXRP(AccountID const &c)
Definition AccountID.h:71
constexpr base_uint< Bits, Tag > operator+(base_uint< Bits, Tag > const &a, base_uint< Bits, Tag > const &b)
Definition base_uint.h:603
Number operator-(Number const &x, Number const &y)
Definition Number.h:279
STAmount amountFromJson(SField const &name, Json::Value const &v)
Definition STAmount.cpp:987
STAmount mulRoundStrict(STAmount const &v1, STAmount const &v2, Asset const &asset, bool roundUp)
Number roundToAsset(A const &asset, Number const &value, std::int32_t scale, Number::rounding_mode rounding=Number::getround())
Round an arbitrary precision Number to the precision of a given Asset.
Definition STAmount.h:722
STAmount toSTAmount(IOUAmount const &iou, Issue const &iss)
bool isLegalNet(STAmount const &value)
Definition STAmount.h:592
STAmount amountFromString(Asset const &asset, std::string const &amount)
Definition STAmount.cpp:977
STAmount divRound(STAmount const &v1, STAmount const &v2, Asset const &asset, bool roundUp)
STAmount multiply(STAmount const &amount, Rate const &rate)
Definition Rate2.cpp:34
STAmount roundToScale(STAmount const &value, std::int32_t scale, Number::rounding_mode rounding=Number::getround())
Round an arbitrary precision Amount to the precision of an STAmount that has a given exponent.
constexpr bool operator==(base_uint< Bits, Tag > const &lhs, base_uint< Bits, Tag > const &rhs)
Definition base_uint.h:566
bool amountFromJsonNoThrow(STAmount &result, Json::Value const &jvSource)
bool canAdd(STAmount const &amt1, STAmount const &amt2)
Safely checks if two STAmount values can be added without overflow, underflow, or precision loss.
Definition STAmount.cpp:485
STAmount amountFromQuality(std::uint64_t rate)
Definition STAmount.cpp:965
SerializedTypeID
Definition SField.h:91
std::uint64_t getRate(STAmount const &offerOut, STAmount const &offerIn)
Definition STAmount.cpp:443
constexpr bool isPowerOfTen(T value)
Definition Number.h:18
bool operator!=(Buffer const &lhs, Buffer const &rhs) noexcept
Definition Buffer.h:213
bool operator<=(STAmount const &lhs, STAmount const &rhs)
Definition STAmount.h:621
STAmount mulRound(STAmount const &v1, STAmount const &v2, Asset const &asset, bool roundUp)
bool canSubtract(STAmount const &amt1, STAmount const &amt2)
Determines if it is safe to subtract one STAmount from another.
Definition STAmount.cpp:565
STAmount divRoundStrict(STAmount const &v1, STAmount const &v2, Asset const &asset, bool roundUp)
bool operator>(STAmount const &lhs, STAmount const &rhs)
Definition STAmount.h:615
constexpr std::enable_if_t< std::is_integral_v< Dest > &&std::is_integral_v< Src >, Dest > safe_cast(Src s) noexcept
Definition safe_cast.h:22
Zero allows classes to offer efficient comparisons to zero.
Definition Zero.h:26
Note, should be treated as flags that can be | and &.
Definition STBase.h:18