Skip to content
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

Merged
merged 13 commits into from
Aug 26, 2024

Conversation

gregtatcam
Copy link
Owner

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 enum SOESupportMPT field. TxFormats::TxFormats() is used to declare amount fields supporting both STAmount and STMPTAmount. This provides an additional run-time type-safety.

@gregtatcam gregtatcam force-pushed the feature/mpt-v1-eitheramount branch 3 times, most recently from 02213e0 to 8cba0c3 Compare July 27, 2024 01:34
@gregtatcam gregtatcam force-pushed the feature/mpt-v1-eitheramount branch 7 times, most recently from f1364c9 to 5386172 Compare August 1, 2024 17:15
@gregtatcam gregtatcam force-pushed the feature/mpt-v1-eitheramount branch 3 times, most recently from 1b12d9d to 0126da7 Compare August 6, 2024 16:06
and SF_EITHER_AMOUNT (support MPT).
Add TypedFieldAmount to declare Amount fields.
Extend STObject with getters/setters for SF_AMOUNT fields.
@gregtatcam gregtatcam force-pushed the feature/mpt-v1-eitheramount branch from 0126da7 to 749a80a Compare August 6, 2024 18:49
get(auto&& amount)
{
using TAmnt = std::decay_t<decltype(amount)>;
if constexpr (std::is_same_v<TAmnt, STEitherAmount>)

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

Copy link
Owner Author

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>();

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.

Copy link
Owner Author

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.

Copy link
Owner Author

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())

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this code reachable?

Copy link
Owner Author

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.

@gregtatcam gregtatcam force-pushed the feature/mpt-v1-eitheramount branch from 189362e to 4b2e103 Compare August 13, 2024 15:42
to provide one single check for all tx.
Update unit-tests.
Fix payment for unauthorized holder
@gregtatcam gregtatcam force-pushed the feature/mpt-v1-eitheramount branch from 4b2e103 to 5b77635 Compare August 13, 2024 15:45
@gregtatcam gregtatcam force-pushed the feature/mpt-v1-eitheramount branch from 9b317f6 to 39e8906 Compare August 14, 2024 18:45
to have separate functions for MPT/IOU
handling since there is little overlap
between them.
Remove the check for DeletableAccounts
@gregtatcam gregtatcam force-pushed the feature/mpt-v1-eitheramount branch from fe8e9d2 to 927abd5 Compare August 15, 2024 19:37
MPTAmount&
MPTAmount::operator+=(MPTAmount const& other)
{
value_ += other.value();

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?

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,

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?

Copy link
Owner Author

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;

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?

Copy link
Owner Author

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.

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.

Copy link
Owner Author

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]becausesfAmount` supports MPT.

Copy link

@seelabs seelabs left a 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.

getMPT(uint192 const&);

inline MPT
badMPT()
Copy link

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?

@@ -68,6 +68,7 @@ class STCurrency;
STYPE(STI_UINT128, 4) \
STYPE(STI_UINT256, 5) \
STYPE(STI_AMOUNT, 6) \
STYPE(STI_EITHER_AMOUNT, 6) \
Copy link

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?

@@ -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>;
Copy link

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?

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
Copy link

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
Copy link

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.

std::uint64_t mantissa = 0,
int exponent = 0,
bool negative = false);
STAmount(std::int64_t mantissa, int64_tag_t);
Copy link

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)

@@ -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;
Copy link

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;
};

Copy link

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
@gregtatcam gregtatcam merged commit d2925bd into feature/mpt-v1 Aug 26, 2024
7 of 12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants