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 ripple {
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 static std::uint64_t const cMinValue = 1000000000000000ull;
51 static std::uint64_t const cMaxValue = 9999999999999999ull;
52 static std::uint64_t const cMaxNative = 9000000000000000000ull;
53
54 // Max native value on network.
55 static std::uint64_t const cMaxNativeN = 100000000000000000ull;
56 static std::uint64_t const cIssuedCurrency = 0x8000000000000000ull;
57 static std::uint64_t const cPositive = 0x4000000000000000ull;
58 static std::uint64_t const cMPToken = 0x2000000000000000ull;
60
61 static std::uint64_t const uRateOne;
62
63 //--------------------------------------------------------------------------
64 STAmount(SerialIter& sit, SField const& name);
65
66 struct unchecked
67 {
68 explicit unchecked() = default;
69 };
70
71 // Do not call canonicalize
72 template <AssetType A>
74 SField const& name,
75 A const& asset,
78 bool negative,
79 unchecked);
80
81 template <AssetType A>
83 A const& asset,
86 bool negative,
87 unchecked);
88
89 // Call canonicalize
90 template <AssetType A>
92 SField const& name,
93 A const& asset,
96 bool negative = false);
97
99
100 STAmount(
101 SField const& name,
103 bool negative = false);
104
105 explicit STAmount(std::uint64_t mantissa = 0, bool negative = false);
106
107 explicit STAmount(SField const& name, STAmount const& amt);
108
109 template <AssetType A>
111 A const& asset,
113 int exponent = 0,
114 bool negative = false)
115 : mAsset(asset)
119 {
120 canonicalize();
121 }
122
123 // VFALCO Is this needed when we have the previous signature?
124 template <AssetType A>
125 STAmount(
126 A const& asset,
128 int exponent = 0,
129 bool negative = false);
130
131 template <AssetType A>
132 STAmount(A const& asset, std::int64_t mantissa, int exponent = 0);
133
134 template <AssetType A>
135 STAmount(A const& asset, int mantissa, int exponent = 0);
136
137 template <AssetType A>
138 STAmount(A const& asset, Number const& number)
139 : STAmount(asset, number.mantissa(), number.exponent())
140 {
141 }
142
143 // Legacy support for new-style amounts
144 STAmount(IOUAmount const& amount, Issue const& issue);
145 STAmount(XRPAmount const& amount);
146 STAmount(MPTAmount const& amount, MPTIssue const& mptIssue);
147 operator Number() const;
148
149 //--------------------------------------------------------------------------
150 //
151 // Observers
152 //
153 //--------------------------------------------------------------------------
154
155 int
156 exponent() const noexcept;
157
158 bool
159 native() const noexcept;
160
161 template <ValidIssueType TIss>
162 constexpr bool
163 holds() const noexcept;
164
165 bool
166 negative() const noexcept;
167
168 std::uint64_t
169 mantissa() const noexcept;
170
171 Asset const&
172 asset() const;
173
174 template <ValidIssueType TIss>
175 constexpr TIss const&
176 get() const;
177
178 Issue const&
179 issue() const;
180
181 // These three are deprecated
182 Currency const&
183 getCurrency() const;
184
185 AccountID const&
186 getIssuer() const;
187
188 int
189 signum() const noexcept;
190
193 zeroed() const;
194
195 void
196 setJson(Json::Value&) const;
197
198 STAmount const&
199 value() const noexcept;
200
201 //--------------------------------------------------------------------------
202 //
203 // Operators
204 //
205 //--------------------------------------------------------------------------
206
207 explicit
208 operator bool() const noexcept;
209
210 STAmount&
211 operator+=(STAmount const&);
212 STAmount&
213 operator-=(STAmount const&);
214
215 STAmount& operator=(beast::Zero);
216
217 STAmount&
218 operator=(XRPAmount const& amount);
219
220 STAmount&
221 operator=(Number const&);
222
223 //--------------------------------------------------------------------------
224 //
225 // Modification
226 //
227 //--------------------------------------------------------------------------
228
229 void
230 negate();
231
232 void
233 clear();
234
235 // Zero while copying currency and issuer.
236 void
237 clear(Asset const& asset);
238
239 void
240 setIssuer(AccountID const& uIssuer);
241
243 void
244 setIssue(Asset const& asset);
245
246 //--------------------------------------------------------------------------
247 //
248 // STBase
249 //
250 //--------------------------------------------------------------------------
251
253 getSType() const override;
254
255 std::string
256 getFullText() const override;
257
258 std::string
259 getText() const override;
260
261 Json::Value getJson(JsonOptions = JsonOptions::none) const override;
262
263 void
264 add(Serializer& s) const override;
265
266 bool
267 isEquivalent(STBase const& t) const override;
268
269 bool
270 isDefault() const override;
271
273 xrp() const;
275 iou() const;
277 mpt() const;
278
279private:
280 static std::unique_ptr<STAmount>
281 construct(SerialIter&, SField const& name);
282
283 void
284 set(std::int64_t v);
285 void
286 canonicalize();
287
288 STBase*
289 copy(std::size_t n, void* buf) const override;
290 STBase*
291 move(std::size_t n, void* buf) override;
292
293 STAmount&
294 operator=(IOUAmount const& iou);
295
296 friend class detail::STVar;
297
298 friend STAmount
299 operator+(STAmount const& v1, STAmount const& v2);
300};
301
302template <AssetType A>
304 SField const& name,
305 A const& asset,
308 bool negative,
309 unchecked)
310 : STBase(name)
311 , mAsset(asset)
315{
316}
317
318template <AssetType A>
328
329template <AssetType A>
331 SField const& name,
332 A const& asset,
333 std::uint64_t mantissa,
334 int exponent,
335 bool negative)
336 : STBase(name)
337 , mAsset(asset)
338 , mValue(mantissa)
339 , mOffset(exponent)
340 , mIsNegative(negative)
341{
342 // mValue is uint64, but needs to fit in the range of int64
343 XRPL_ASSERT(
345 "ripple::STAmount::STAmount(SField, A, std::uint64_t, int, bool) : "
346 "maximum mantissa input");
347 canonicalize();
348}
349
350template <AssetType A>
351STAmount::STAmount(A const& asset, std::int64_t mantissa, int exponent)
352 : mAsset(asset), mOffset(exponent)
353{
354 set(mantissa);
355 canonicalize();
356}
357
358template <AssetType A>
360 A const& asset,
361 std::uint32_t mantissa,
362 int exponent,
363 bool negative)
364 : STAmount(asset, safe_cast<std::uint64_t>(mantissa), exponent, negative)
365{
366}
367
368template <AssetType A>
369STAmount::STAmount(A const& asset, int mantissa, int exponent)
370 : STAmount(asset, safe_cast<std::int64_t>(mantissa), exponent)
371{
372}
373
374// Legacy support for new-style amounts
375inline STAmount::STAmount(IOUAmount const& amount, Issue const& issue)
376 : mAsset(issue)
377 , mOffset(amount.exponent())
378 , mIsNegative(amount < beast::zero)
379{
380 if (mIsNegative)
381 mValue = unsafe_cast<std::uint64_t>(-amount.mantissa());
382 else
383 mValue = unsafe_cast<std::uint64_t>(amount.mantissa());
384
385 canonicalize();
386}
387
388inline STAmount::STAmount(MPTAmount const& amount, MPTIssue const& mptIssue)
389 : mAsset(mptIssue), mOffset(0), mIsNegative(amount < beast::zero)
390{
391 if (mIsNegative)
392 mValue = unsafe_cast<std::uint64_t>(-amount.value());
393 else
394 mValue = unsafe_cast<std::uint64_t>(amount.value());
395
396 canonicalize();
397}
398
399//------------------------------------------------------------------------------
400//
401// Creation
402//
403//------------------------------------------------------------------------------
404
405// VFALCO TODO The parameter type should be Quality not uint64_t
408
410amountFromString(Asset const& asset, std::string const& amount);
411
413amountFromJson(SField const& name, Json::Value const& v);
414
415bool
416amountFromJsonNoThrow(STAmount& result, Json::Value const& jvSource);
417
418// IOUAmount and XRPAmount define toSTAmount, defining this
419// trivial conversion here makes writing generic code easier
420inline STAmount const&
422{
423 return a;
424}
425
426//------------------------------------------------------------------------------
427//
428// Observers
429//
430//------------------------------------------------------------------------------
431
432inline int
433STAmount::exponent() const noexcept
434{
435 return mOffset;
436}
437
438inline bool
439STAmount::native() const noexcept
440{
441 return mAsset.native();
442}
443
444template <ValidIssueType TIss>
445constexpr bool
446STAmount::holds() const noexcept
447{
448 return mAsset.holds<TIss>();
449}
450
451inline bool
452STAmount::negative() const noexcept
453{
454 return mIsNegative;
455}
456
457inline std::uint64_t
458STAmount::mantissa() const noexcept
459{
460 return mValue;
461}
462
463inline Asset const&
465{
466 return mAsset;
467}
468
469template <ValidIssueType TIss>
470constexpr TIss const&
472{
473 return mAsset.get<TIss>();
474}
475
476inline Issue const&
478{
479 return get<Issue>();
480}
481
482inline Currency const&
484{
485 return mAsset.get<Issue>().currency;
486}
487
488inline AccountID const&
490{
491 return mAsset.getIssuer();
492}
493
494inline int
495STAmount::signum() const noexcept
496{
497 return mValue ? (mIsNegative ? -1 : 1) : 0;
498}
499
500inline STAmount
502{
503 return STAmount(mAsset);
504}
505
506inline STAmount::operator bool() const noexcept
507{
508 return *this != beast::zero;
509}
510
511inline STAmount::operator Number() const
512{
513 if (native())
514 return xrp();
515 if (mAsset.holds<MPTIssue>())
516 return mpt();
517 return iou();
518}
519
520inline STAmount&
522{
523 clear();
524 return *this;
525}
526
527inline STAmount&
529{
530 *this = STAmount(amount);
531 return *this;
532}
533
534inline STAmount&
536{
537 mIsNegative = number.mantissa() < 0;
538 mValue = mIsNegative ? -number.mantissa() : number.mantissa();
539 mOffset = number.exponent();
540 canonicalize();
541 return *this;
542}
543
544inline void
546{
547 if (*this != beast::zero)
549}
550
551inline void
553{
554 // The -100 is used to allow 0 to sort less than a small positive values
555 // which have a negative exponent.
556 mOffset = native() ? 0 : -100;
557 mValue = 0;
558 mIsNegative = false;
559}
560
561inline void
563{
565 clear();
566}
567
568inline void
570{
571 mAsset.get<Issue>().account = uIssuer;
572}
573
574inline STAmount const&
575STAmount::value() const noexcept
576{
577 return *this;
578}
579
580inline bool
581isLegalNet(STAmount const& value)
582{
583 return !value.native() || (value.mantissa() <= STAmount::cMaxNativeN);
584}
585
586//------------------------------------------------------------------------------
587//
588// Operators
589//
590//------------------------------------------------------------------------------
591
592bool
593operator==(STAmount const& lhs, STAmount const& rhs);
594bool
595operator<(STAmount const& lhs, STAmount const& rhs);
596
597inline bool
598operator!=(STAmount const& lhs, STAmount const& rhs)
599{
600 return !(lhs == rhs);
601}
602
603inline bool
604operator>(STAmount const& lhs, STAmount const& rhs)
605{
606 return rhs < lhs;
607}
608
609inline bool
610operator<=(STAmount const& lhs, STAmount const& rhs)
611{
612 return !(rhs < lhs);
613}
614
615inline bool
616operator>=(STAmount const& lhs, STAmount const& rhs)
617{
618 return !(lhs < rhs);
619}
620
621STAmount
622operator-(STAmount const& value);
623
624//------------------------------------------------------------------------------
625//
626// Arithmetic
627//
628//------------------------------------------------------------------------------
629
630STAmount
631operator+(STAmount const& v1, STAmount const& v2);
632STAmount
633operator-(STAmount const& v1, STAmount const& v2);
634
635STAmount
636divide(STAmount const& v1, STAmount const& v2, Asset const& asset);
637
638STAmount
639multiply(STAmount const& v1, STAmount const& v2, Asset const& asset);
640
641// multiply rounding result in specified direction
642STAmount
644 STAmount const& v1,
645 STAmount const& v2,
646 Asset const& asset,
647 bool roundUp);
648
649// multiply following the rounding directions more precisely.
650STAmount
652 STAmount const& v1,
653 STAmount const& v2,
654 Asset const& asset,
655 bool roundUp);
656
657// divide rounding result in specified direction
658STAmount
660 STAmount const& v1,
661 STAmount const& v2,
662 Asset const& asset,
663 bool roundUp);
664
665// divide following the rounding directions more precisely.
666STAmount
668 STAmount const& v1,
669 STAmount const& v2,
670 Asset const& asset,
671 bool roundUp);
672
673// Someone is offering X for Y, what is the rate?
674// Rate: smaller is better, the taker wants the most out: in/out
675// VFALCO TODO Return a Quality object
677getRate(STAmount const& offerOut, STAmount const& offerIn);
678
679//------------------------------------------------------------------------------
680
681inline bool
682isXRP(STAmount const& amount)
683{
684 return amount.native();
685}
686
687bool
688canAdd(STAmount const& amt1, STAmount const& amt2);
689
690bool
691canSubtract(STAmount const& amt1, STAmount const& amt2);
692
693} // namespace ripple
694
695//------------------------------------------------------------------------------
696namespace Json {
697template <>
698inline ripple::STAmount
699getOrThrow(Json::Value const& v, ripple::SField const& field)
700{
701 using namespace ripple;
702 Json::StaticString const& key = field.getJsonName();
703 if (!v.isMember(key))
704 Throw<JsonMissingKeyError>(key);
705 Json::Value const& inner = v[key];
706 return amountFromJson(field, inner);
707}
708} // namespace Json
709#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.
bool native() const
Definition Asset.h:82
constexpr TIss const & get() const
AccountID const & getIssuer() const
Definition Asset.cpp:17
constexpr bool holds() const
Definition Asset.h:113
Tracks the number of instances of an object.
Floating point representation of amounts with high dynamic range.
Definition IOUAmount.h:27
std::int64_t mantissa() const noexcept
Definition IOUAmount.h:159
A currency issued by an account.
Definition Issue.h:14
constexpr value_type value() const
Returns the underlying value.
Definition MPTAmount.h:114
constexpr int exponent() const noexcept
Definition Number.h:217
constexpr rep mantissa() const noexcept
Definition Number.h:211
Identifies fields.
Definition SField.h:127
constexpr bool holds() const noexcept
Definition STAmount.h:446
IOUAmount iou() const
Definition STAmount.cpp:280
Json::Value getJson(JsonOptions=JsonOptions::none) const override
Definition STAmount.cpp:753
static std::uint64_t const cMaxNativeN
Definition STAmount.h:55
STAmount & operator=(beast::Zero)
Definition STAmount.h:521
int exponent() const noexcept
Definition STAmount.h:433
STBase * move(std::size_t n, void *buf) override
Definition STAmount.cpp:253
Asset const & asset() const
Definition STAmount.h:464
static std::uint64_t const cPositive
Definition STAmount.h:57
constexpr TIss const & get() const
void setIssuer(AccountID const &uIssuer)
Definition STAmount.h:569
static int const cMaxOffset
Definition STAmount.h:47
static int const cMinOffset
Definition STAmount.h:46
Currency const & getCurrency() const
Definition STAmount.h:483
friend class detail::STVar
Definition STAmount.h:296
static std::uint64_t const cMinValue
Definition STAmount.h:50
static std::unique_ptr< STAmount > construct(SerialIter &, SField const &name)
Definition STAmount.cpp:241
void setIssue(Asset const &asset)
Set the Issue for this amount.
Definition STAmount.cpp:429
XRPAmount xrp() const
Definition STAmount.cpp:264
void setJson(Json::Value &) const
Definition STAmount.cpp:624
bool isDefault() const override
Definition STAmount.cpp:807
void add(Serializer &s) const override
Definition STAmount.cpp:761
static std::uint64_t const cIssuedCurrency
Definition STAmount.h:56
static std::uint64_t const cMPToken
Definition STAmount.h:58
SerializedTypeID getSType() const override
Definition STAmount.cpp:648
mantissa_type mValue
Definition STAmount.h:39
int signum() const noexcept
Definition STAmount.h:495
static std::uint64_t const cMaxValue
Definition STAmount.h:51
STAmount const & value() const noexcept
Definition STAmount.h:575
std::string getText() const override
Definition STAmount.cpp:664
bool negative() const noexcept
Definition STAmount.h:452
AccountID const & getIssuer() const
Definition STAmount.h:489
bool isEquivalent(STBase const &t) const override
Definition STAmount.cpp:800
STAmount(A const &asset, std::uint64_t mantissa=0, int exponent=0, bool negative=false)
Definition STAmount.h:110
STBase * copy(std::size_t n, void *buf) const override
Definition STAmount.cpp:247
MPTAmount mpt() const
Definition STAmount.cpp:295
static std::uint64_t const cValueMask
Definition STAmount.h:59
exponent_type mOffset
Definition STAmount.h:40
Issue const & issue() const
Definition STAmount.h:477
static std::uint64_t const cMaxNative
Definition STAmount.h:52
STAmount(A const &asset, Number const &number)
Definition STAmount.h:138
void set(std::int64_t v)
Definition STAmount.cpp:948
std::uint64_t mantissa() const noexcept
Definition STAmount.h:458
std::string getFullText() const override
Definition STAmount.cpp:654
STAmount(SerialIter &sit, SField const &name)
Definition STAmount.cpp:101
bool native() const noexcept
Definition STAmount.h:439
STAmount zeroed() const
Returns a zero value with the same issuer and currency.
Definition STAmount.h:501
static std::uint64_t const uRateOne
Definition STAmount.h:61
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
ripple::AccountID getOrThrow(Json::Value const &v, ripple::SField const &field)
Definition AccountID.h:112
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
bool operator<=(STAmount const &lhs, STAmount const &rhs)
Definition STAmount.h:610
STAmount divide(STAmount const &amount, Rate const &rate)
Definition Rate2.cpp:74
bool isXRP(AccountID const &c)
Definition AccountID.h:71
bool operator!=(Buffer const &lhs, Buffer const &rhs) noexcept
Definition Buffer.h:213
bool canSubtract(STAmount const &amt1, STAmount const &amt2)
Determines if it is safe to subtract one STAmount from another.
Definition STAmount.cpp:566
STAmount divRoundStrict(STAmount const &v1, STAmount const &v2, Asset const &asset, bool roundUp)
STAmount amountFromJson(SField const &name, Json::Value const &v)
Definition STAmount.cpp:987
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:486
bool isLegalNet(STAmount const &value)
Definition STAmount.h:581
SerializedTypeID
Definition SField.h:91
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
STAmount toSTAmount(IOUAmount const &iou, Issue const &iss)
STAmount amountFromQuality(std::uint64_t rate)
Definition STAmount.cpp:965
STAmount multiply(STAmount const &amount, Rate const &rate)
Definition Rate2.cpp:34
std::uint64_t getRate(STAmount const &offerOut, STAmount const &offerIn)
Definition STAmount.cpp:444
bool operator>(STAmount const &lhs, STAmount const &rhs)
Definition STAmount.h:604
bool amountFromJsonNoThrow(STAmount &result, Json::Value const &jvSource)
bool operator<(Slice const &lhs, Slice const &rhs) noexcept
Definition Slice.h:204
STAmount divRound(STAmount const &v1, STAmount const &v2, Asset const &asset, bool roundUp)
Number operator-(Number const &x, Number const &y)
Definition Number.h:281
STAmount amountFromString(Asset const &asset, std::string const &amount)
Definition STAmount.cpp:977
STAmount mulRound(STAmount const &v1, STAmount const &v2, Asset const &asset, bool roundUp)
constexpr base_uint< Bits, Tag > operator+(base_uint< Bits, Tag > const &a, base_uint< Bits, Tag > const &b)
Definition base_uint.h:603
constexpr bool operator==(base_uint< Bits, Tag > const &lhs, base_uint< Bits, Tag > const &rhs)
Definition base_uint.h:566
STAmount mulRoundStrict(STAmount const &v1, STAmount const &v2, Asset const &asset, bool roundUp)
bool operator>=(STAmount const &lhs, STAmount const &rhs)
Definition STAmount.h:616
STL namespace.
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