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

Unsigned MASP Changes in SDK #3716

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open

Conversation

grarco
Copy link
Contributor

@grarco grarco commented Aug 28, 2024

Describe your changes

Closes #3425.

Modifies the Changes type in the SDK to wrap U128Sum instead of I128Sum since changes are guaranteed to be non-negative. Also adjusts from_masp_denominated_i128 and swap the calls to from_nonnegative for from_pair.

Checklist before merging

  • If this PR has some consensus breaking changes, I added the corresponding breaking:: labels
    • This will require 2 reviewers to approve the changes

grarco added a commit that referenced this pull request Aug 28, 2024
@grarco grarco force-pushed the grarco/unsigned-change-in-sdk branch from b22fefb to f0a9d8b Compare August 28, 2024 13:15
Copy link

codecov bot commented Aug 28, 2024

Codecov Report

Attention: Patch coverage is 63.63636% with 16 lines in your changes missing coverage. Please review.

Project coverage is 72.47%. Comparing base (6d1b9da) to head (6364873).
Report is 188 commits behind head on main.

Files with missing lines Patch % Lines
crates/shielded_token/src/masp/shielded_wallet.rs 54.28% 16 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main    #3716   +/-   ##
=======================================
  Coverage   72.47%   72.47%           
=======================================
  Files         338      338           
  Lines      104130   104128    -2     
=======================================
- Hits        75470    75469    -1     
+ Misses      28660    28659    -1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@grarco grarco marked this pull request as ready for review August 28, 2024 13:34
@grarco grarco requested a review from murisi August 28, 2024 13:34
grarco added a commit that referenced this pull request Aug 28, 2024
@grarco grarco force-pushed the grarco/unsigned-change-in-sdk branch from f0a9d8b to 11041fb Compare August 28, 2024 14:37
grarco added a commit that referenced this pull request Aug 28, 2024
@grarco grarco force-pushed the grarco/unsigned-change-in-sdk branch from 11041fb to 6c339f2 Compare August 28, 2024 15:23
grarco added a commit that referenced this pull request Sep 6, 2024
@grarco grarco force-pushed the grarco/unsigned-change-in-sdk branch from 6c339f2 to 49a0996 Compare September 6, 2024 08:48
@grarco grarco force-pushed the grarco/unsigned-change-in-sdk branch from 49a0996 to 6364873 Compare September 6, 2024 13:56
Copy link
Contributor

@murisi murisi left a comment

Choose a reason for hiding this comment

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

Probably these changes are okay for the most part. The MASP crate uses I128Sums to represent value balances because we needed a signed type that can holds sums and differences of u64s without overflowing or underflowing. Given this, while I understand that it is conceptually clearer to hold unsigned amounts in U128Sums. It seems to me that this comes at the cost of introducing another integer type U128Sum and sometimes having to do fallible conversions from U128Sums to I128Sums for interoperability with the MASP crate. I guess this is fine if we understand that due to the fallible runtime conversions, the U128Sums (just like the I128Sums that they are replacing) can really only hold U127Sums.

I128Sum::try_from_sum(output_amt.clone()).map_err(
|e| {
TransferErr::General(Error::Other(format!(
"Fee amount is expected to be \
Copy link
Contributor

Choose a reason for hiding this comment

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

Given that this error would be triggered by a failed conversion from u128 to i128, shouldn't this error message be to the effect that the fee amount is too large?

let denominated_output_amt = context
.shielded_mut()
.await
.convert_masp_amount_to_namada(
context.client(),
// Safe to unwrap
denoms.get(token).unwrap().to_owned(),
output_amt.clone(),
I128Sum::try_from_sum(output_amt.clone()).map_err(
Copy link
Contributor

Choose a reason for hiding this comment

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

I understand that this conversion is necessary to placate the type checker, but is this conversion necessary at the conceptual level? I could imagine convert_masp_amount_to_namada being generalized or being given a twin that takes U128s instead of I128.

@@ -1852,7 +1836,9 @@ impl<U: ShieldedUtils + MaybeSend + MaybeSync> ShieldedContext<U> {
for (asset_type, fee_amt) in fees.clone().components() {
let input_amt = I128Sum::from_nonnegative(
asset_type.to_owned(),
*fee_amt,
i128::try_from(*fee_amt).map_err(|e| {
Copy link
Contributor

Choose a reason for hiding this comment

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

It seems to me like we can avoid this fallible conversion if we declare input_amt as let input_amt = U128Sum::from_pair(asset_type.to_owned(), *fee_amt) or something similar. But doing this would involve using an analogue of convert_masp_amount_to_namada that takes U128Sums...

@@ -1915,7 +1901,12 @@ impl<U: ShieldedUtils + MaybeSend + MaybeSync> ShieldedContext<U> {
)
.await?;

fees -= &output_amt;
fees -= U128Sum::try_from_sum(output_amt).map_err(|e| {
Copy link
Contributor

Choose a reason for hiding this comment

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

The fallible conversion here and at

i128::try_from(*fee_amt).map_err(|e| {
could be replaced with one fallible conversion of found_amt (declared at
let Some(found_amt) = Self::add_inputs(
) to a U128Sum.

let positioned_amt = token::Amount::from_masp_denominated_i128(
*val,
let positioned_amt = token::Amount::from_masp_denominated_u128(
*val as u128,
Copy link
Contributor

Choose a reason for hiding this comment

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

Given that a caller might call this function with negative entries inside amt, shouldn't we first check to see if val can be converted to a u128? Or better yet, shouldn't we just change the parameter amt: I128Sum to amt: U128Sum?

@@ -1925,8 +1916,14 @@ impl<U: ShieldedUtils + MaybeSend + MaybeSync> ShieldedContext<U> {
}

if !fees.is_zero() {
let signed_fees = I128Sum::try_from_sum(fees).map_err(|e| {
Copy link
Contributor

Choose a reason for hiding this comment

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

I guess this error occurs when fee: U128Sum is too large to be contained by a I128Sum. This sort of error (u128 too large for i128) seems to be less clearly defined than those that were produced when an I128Sum unexpectedly contained a negative quantity. I guess this is because it's clearer that quantities like fees can only ever be positive (or maybe zero).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Make Changes unsigned
2 participants