-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use STEitherAmount as a variant of STAmount and STMPTAmount #30
Conversation
02213e0
to
8cba0c3
Compare
f1364c9
to
5386172
Compare
1b12d9d
to
0126da7
Compare
and SF_EITHER_AMOUNT (support MPT). Add TypedFieldAmount to declare Amount fields. Extend STObject with getters/setters for SF_AMOUNT fields.
0126da7
to
749a80a
Compare
get(auto&& amount) | ||
{ | ||
using TAmnt = std::decay_t<decltype(amount)>; | ||
if constexpr (std::is_same_v<TAmnt, STEitherAmount>) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this to support get<STEitherAmount>
? I don't think it is being used anywhere
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's used to get either STAmount
or STMPTAmount
. See the concept ValidAmountType
.
if constexpr (std::is_same_v<TAmnt, STEitherAmount>) | ||
{ | ||
if constexpr (std::is_lvalue_reference_v<decltype(amount)>) | ||
return amount.template get<T>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would this call the either one of two get()
?:
template <ValidAmountType T>
T const&
STEitherAmount::get() const
{
if (std::holds_alternative<T>(amount_))
return std::get<T>(amount_);
Throw<std::logic_error>("Invalid STEitherAmount conversion");
}
template <ValidAmountType T>
T&
STEitherAmount::get()
{
if (std::holds_alternative<T>(amount_))
return std::get<T>(amount_);
Throw<std::logic_error>("Invalid STEitherAmount conversion");
It seems like both of them would throw.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One is const and the other one is not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And, yes one of them is going to be called and will throw if the requested type doesn't match the type that the variant holds.
}, | ||
lhs.getValue(), | ||
rhs.getValue()); | ||
if (lhs.isIssue() == rhs.isIssue()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this code reachable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. It's not reachable. I was debating what version to use and forgot to remove it.
189362e
to
4b2e103
Compare
to provide one single check for all tx. Update unit-tests. Fix payment for unauthorized holder
4b2e103
to
5b77635
Compare
9b317f6
to
39e8906
Compare
to have separate functions for MPT/IOU handling since there is little overlap between them. Remove the check for DeletableAccounts
fe8e9d2
to
927abd5
Compare
MPTAmount& | ||
MPTAmount::operator+=(MPTAmount const& other) | ||
{ | ||
value_ += other.value(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does it ever have to check overflow here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nevermind, its checked in the constructor
@@ -1344,22 +1344,22 @@ class STTx_test : public beast::unit_test::suite | |||
0x73, 0x00, 0x81, 0x14, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x65, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0xe5, 0xfe, 0xf3, 0xe7, 0xe5, 0x65, 0x24, 0x00, 0x00, 0x00, 0x00, | |||
0x20, 0x1e, 0x00, 0x6f, 0x00, 0x00, 0x20, 0x1f, 0x03, 0xf6, 0x00, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what's changing this for?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I took this change from Howard's MPT branch. One of the tests fails without it.
@@ -520,7 +551,7 @@ extern SF_UINT256 const sfHookNamespace; | |||
extern SF_UINT256 const sfHookSetTxnID; | |||
|
|||
// currency amount (common) | |||
extern SF_AMOUNT const sfAmount; | |||
extern SF_EITHER_AMOUNT const sfAmount; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why wouldn't we need to change the other Amount types like sfBalance to SF_EITHER_AMOUNT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SF_EITHER_AMOUNT
is used to indicate that this field can be either STAmount
or STMPTAmount
. SF_AMOUNT
indicates that the field can be only STAmount
. Only sfAmount
supports MPT in the first release. What this actually does is this: when you access sfAmount
as tx[sfAmount]
then it returns STEitherAmount
and you have explicitly get the amount with get<>()
. If you access sfBalance
as tx[sfBalance]
then it returns STAmount
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes I understand that, but don't we already have something like this inside the TxFormat.cpp?
{sfAmount, soeREQUIRED, soeMPTSupported},
Or i guess this one is compile-type check where as the SOElement is runtime.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TxFormat defines a run-time check, which is done in invalidMPTAmountInTx()
. SF_AMOUNT
and SF_EITHER_AMOUNT
declare different types for the fields that don't support and support MPT. These types provide overload for STObject::operator[]()
, which returns either STAmount
or STEitherAmount
depending on the field type. This is compile time. For instance, this is going to fail for sfAmount
: STAmount const amount = tx[sfAmount]because
sfAmount` supports MPT.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the approach is fine. 👍 from me. I did not do a detailed review at all, I'm restricted myself to high-level considerations. However, if I did notice anything while I looked at the code I made a note and left a comment. That doesn't mean the comment is important, they are just things I noticed and wanted to point out.
include/xrpl/protocol/MPTIssue.h
Outdated
getMPT(uint192 const&); | ||
|
||
inline MPT | ||
badMPT() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be better if we didn't need a sentinel value for a bad mpt. Is this really needed?
include/xrpl/protocol/SField.h
Outdated
@@ -68,6 +68,7 @@ class STCurrency; | |||
STYPE(STI_UINT128, 4) \ | |||
STYPE(STI_UINT256, 5) \ | |||
STYPE(STI_AMOUNT, 6) \ | |||
STYPE(STI_EITHER_AMOUNT, 6) \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see this duplicates st amount, and I think I know why it's done. Could we remove STI_AMOUNT?
include/xrpl/protocol/SField.h
Outdated
@@ -346,7 +376,8 @@ using SF_UINT384 = TypedField<STBitString<384>>; | |||
using SF_UINT512 = TypedField<STBitString<512>>; | |||
|
|||
using SF_ACCOUNT = TypedField<STAccount>; | |||
using SF_AMOUNT = TypedField<STAmount>; | |||
using SF_AMOUNT = TypedFieldAmount<SFieldMPT::No>; | |||
using SF_EITHER_AMOUNT = TypedFieldAmount<SFieldMPT::Yes>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems misleading to me. The template parameter controls whether the type can contain an mpt, but it doesn't necessarily need to hold an mpt - it can still hold an stamount. Maybe rename "Yes" to something else? MaybeMPT
or somesuch?
include/xrpl/protocol/STAmount.h
Outdated
concept AssetType = std::is_same_v<A, Issue> || std::is_same_v<A, MPT> || | ||
std::is_same_v<A, Asset> || std::is_convertible_v<A, Issue> || | ||
std::is_convertible_v<A, Asset>; | ||
struct int64_tag_t |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider narrowing the scope of this declaration.
@@ -49,15 +46,15 @@ concept AssetType = std::is_same_v<A, Issue> || std::is_same_v<A, MPT> || | |||
// Wire form: | |||
// High 8 bits are (offset+142), legal range is, 80 to 22 inclusive | |||
// Low 56 bits are value, legal range is 10^15 to (10^16 - 1) inclusive | |||
class STAmount final : public STBase, public CountedObject<STAmount> | |||
class STAmount final |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this no longer inherits from STBase consider renaming it.
include/xrpl/protocol/STAmount.h
Outdated
std::uint64_t mantissa = 0, | ||
int exponent = 0, | ||
bool negative = false); | ||
STAmount(std::int64_t mantissa, int64_tag_t); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs a comment. I know the existing code is way undercommented, but new code should be better documented. (for this and other changes in this changeset, but this is the first one that caught my eye)
include/xrpl/protocol/STObject.h
Outdated
@@ -53,12 +54,15 @@ throwFieldNotFound(SField const& field) | |||
|
|||
class STObject : public STBase, public CountedObject<STObject> | |||
{ | |||
template <typename T, SFieldMPT M> | |||
using ValueType = std::conditional<M == SFieldMPT::No, STAmount, T>::type; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be better if STObject didn't know anything about STAmount.
public: | ||
explicit MPTTag() = default; | ||
}; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll leave a comment here, but around line 58 there's the following code:
/** MPT is a 192-bit hash representing MPTID. */
using MPT = std::pair<std::uint32_t, AccountID>;
For better type safety, consider making a class for MPT. I'm also not sure this is the best place for this declaration.
Also, around line 69 is the following declaration:
MPT const&
noMPT();
It would be better if we didn't need these sentinal classes. What is the purpose of this? I don't see it used.
* Replace MPT:pair<uint32,AccountID> with MPTID:uint192 * Remove SFieldMPT * Replated TypedFieldAmount with generic TypedFieldVariant to handle STEitherAmount * Update comments
Introduce STEitherAmount to represent STAmount and STMPTAmount as a variant. Accessing specific amount field requires a call to get().
Add amendment guards to all transactions with STI_AMOUNT field.
Extend
SOElement
with enumSOESupportMPT
field.TxFormats::TxFormats()
is used to declare amount fields supporting bothSTAmount
andSTMPTAmount
. This provides an additional run-time type-safety.