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

MASP vp multiple txs #2690

Closed
wants to merge 18 commits into from
Closed

MASP vp multiple txs #2690

wants to merge 18 commits into from

Conversation

grarco
Copy link
Contributor

@grarco grarco commented Feb 21, 2024

Describe your changes

Closes #2595.

Modifies the MASP vp to allow multiple transfers in a single transaction. To achieve this, some constraints had to be removes (like the checks on the presence/absence of the transparent bundle, transparent inputs and outputs). Since we cannot expect a singles source/target anymore some changes were made, most importantly:

  • the checks on the sapling bundle have been modified to always run and to not expect the presence of shielded inputs
  • the checks on the transparent bundle have been modified to run against against all the changed balance keys instead of expecting a specific source/target

No changes to the SDK have been done in this PR because, at least for the moment, we still rely on the Transfer object to recover the Transaction, and so other tx_data types won't work, leading to an impossibility to effectively take advantage of these vp updates.

Indicate on which release or other PRs this topic is based on

#2621

Checklist before merging to draft

  • I have added a changelog
  • Git history is in acceptable state

@grarco grarco mentioned this pull request Feb 21, 2024
2 tasks
@grarco grarco requested a review from murisi February 21, 2024 19:35
Copy link

codecov bot commented Feb 21, 2024

Codecov Report

Attention: Patch coverage is 0% with 325 lines in your changes are missing coverage. Please review.

Project coverage is 53.93%. Comparing base (2535c9c) to head (ac55fc4).

Files Patch % Lines
crates/namada/src/ledger/native_vp/masp.rs 0.00% 275 Missing ⚠️
crates/namada/src/ledger/native_vp/mod.rs 0.00% 31 Missing ⚠️
crates/trans_token/src/storage_key.rs 0.00% 10 Missing ⚠️
crates/sdk/src/masp.rs 0.00% 9 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2690      +/-   ##
==========================================
- Coverage   53.95%   53.93%   -0.03%     
==========================================
  Files         308      308              
  Lines      100018   100054      +36     
==========================================
- Hits        53967    53963       -4     
- Misses      46051    46091      +40     

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

grarco added a commit that referenced this pull request Feb 21, 2024
@grarco grarco marked this pull request as ready for review February 21, 2024 19:57
@grarco grarco marked this pull request as draft February 22, 2024 09:05
token,
amount,
})
if let ShieldedActionOwner::Minted = counterpart {
Copy link
Contributor Author

@grarco grarco Feb 22, 2024

Choose a reason for hiding this comment

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

I think this could be removed if we only validated the absolute value of the balance changes instead of the value and the sign. I'm not sure though if this is completely safe to do

Copy link
Contributor

Choose a reason for hiding this comment

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

Can I just clarify the following?: When receiving a simple IBC transfer, the Transaction will have a vin from the IBC account's transparent address and no vouts (because the amount will be in the shielded outputs)? And because of this, validate_transparent_bundle computes a negative delta? Is this the reason why we negate diff here?

Copy link
Contributor Author

@grarco grarco Mar 1, 2024

Choose a reason for hiding this comment

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

To my understating when we receive a shielded action two things happen:

  1. We mint the token amount in the #Multitoken/{token_addr}/balance/minted balance (this should be the case only if we are receiving a foreign token, if we are receiving back the native token than we should unescrow from #Multitoken/{token_addr}/balance/#Ibc)
  2. The amount is shielded, thus increasing the transparent balance of the MASP, but this does not reduce the amount of the minted balance, so in this case the sum of the amounts does not collapse to 0, leading to the need to mock an opposite balance change for the minted balance to make the computation work

grarco added a commit that referenced this pull request Feb 23, 2024
@grarco grarco marked this pull request as ready for review February 23, 2024 13:28
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.

Nice, I like the way you have structured the MASP VP. I just think that perhaps some of the logic could maybe be simplified and made less verbose. I also think we should take advantage of Transaction::sapling_value_balance() in the MASP VP checks somehow since that value tells us how much is flowing into/out of the shielded pool for a given Transaction.

I've sketched some of my ideas here: https://github.com/anoma/namada/tree/murisi/multi-tx-masp-vp-experiments .

let mut token_bundle_balances = BTreeMap::default();

// To help recognize asset types not in the conversion tree
let unepoched_tokens = unepoched_tokens(token, denom)?;
Copy link
Contributor

Choose a reason for hiding this comment

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

It might be easier to compute and accumulate all unepoched_tokens corresponding to ChangedBalance::masp's elements in the loop in validate_state_and_get_transfer_data. Doing that would remove this loop body's direct dependence on token, and hence potentially allow us to remove the for token in changed_balances.masp { loop in this function. Doing that might allows us to reduce the loop nesting in this function.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually we still depend on the token binding in two more places inside this loop:

  1. When checking the conversion
  2. When matching the transparent bundle agains the changed keys in storage

For the second point we could simply iterate on the entire token_bundle_balances but for the first point I suspect we'd need to iterate anyway, so we'll end up just moving the for loop to a different place instead of removing it


match delta_balance {
Some(delta_balance)
if delta_balance == &delta_bundle => {}
Copy link
Contributor

@murisi murisi Feb 29, 2024

Choose a reason for hiding this comment

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

It seems that we check here that the transparent account balance changes recorded in the MASP transaction reflect the transparent account balance changes reflected in the keys. So if the key changes indicate that Bertha's balance has increased by +1 BTC, a transaction with a vin from Bertha of 5 BTC and a vout of 6 BTC TO Bertha would pass, right? Do we have any checks to prevent the VP from accepting a vin from Bertha of (5+x) BTC and a vout of (6+x) BTC (where x is large enough to exceed relevant source account balances)? If not, does anything in the client depend on the vins and vouts correctness (and not just the correctness of the delta)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah good point. We don't have such a check, so it's possible for a transparent address to withdraw more than it owns if in the same transaction it also receives an amount great enough to compensate for this difference. To my understanding though, this is also the logic used in the multitoken vp. The client seems to be working only with the deltas implied by the transparent bundle (atm we use the changed balance keys only to determine who's the sender and who's the receiver but we can perhaps rework that)


// Iterate over the delta balances described by the transparent
// bundle and verify that these match the actual modifications
// in storage NOTE: this effectively prevent the
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this restriction (of not allowing the same addresses/tokens to be involved in other transparent transfers in the same tx) conceptually necessary? Or is it just an accidental consequence of our current design?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No this is an unfortunate consequence of this logic, I'd be very happy if we could lift this constraint

token,
amount,
})
if let ShieldedActionOwner::Minted = counterpart {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can I just clarify the following?: When receiving a simple IBC transfer, the Transaction will have a vin from the IBC account's transparent address and no vouts (because the amount will be in the shielded outputs)? And because of this, validate_transparent_bundle computes a negative delta? Is this the reason why we negate diff here?

);
return Ok(false);
}
} else if !changed_balances.masp.is_empty() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Is it possible for the MASP transparent balance to be incorrectly changed when transparent bundles are there? Like imagine a situation where a single Tx causes 5 BTC to be (legitimately) unshielded to Bertha (in the usual way with Transaction - Transfer pair) and simultaneously 10 ETH is transferred from MASP transparent address to Christel (with no corresponding vins or vouts). In this situation shielded_tx.transparent_bundle() would contain only BTC denominated vins and vouts, and changed_balances.masp would contain ETH and BTC. In this situation, which code prevents a positive change in changed_balances.other.get(ETH)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The for loop at line 361 should iterate over all the masp changed balances and then checks the transparent bundle. If the bundle does not contain any data for ETH than token_bundle_balances should not be updated and therefore fail the test at line 579 where we check that the modifications implied by the transparent bundle effectively match to changes in storage. token_bundle_balances is instantiated for every token based on the modifications in the balance keys in storage so it should cover the case you illustrated

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Correction, you're right, the token_bundle_balances would be empty in this case and so this is a bug 👍🏻

@murisi murisi mentioned this pull request Feb 29, 2024
2 tasks
@murisi murisi mentioned this pull request May 6, 2024
2 tasks
murisi pushed a commit that referenced this pull request May 7, 2024
@grarco
Copy link
Contributor Author

grarco commented May 10, 2024

Closed in favor of #3186

@grarco grarco closed this May 10, 2024
brentstone added a commit that referenced this pull request May 21, 2024
* origin/murisi+grarco/multi-tx-masp-vp-rebased2:
  Enable governance to change MASP token map.
  Moved SignedAmount into core and removed use of unchecked arithmetic.
  Use try_fold to build the ChangedBalances object.
  Created a structure for representing conversion leafs.
  Factored the accumulation code out of verify_sapling_balancing_value.
  Updated the WASM binaries.
  Extend SignedAmount to hold MASP value balance.
  Use a MASP crate that guarantees ValueSums.
  Make MASP VP accept IBC transactions.
  Ensure that all implied transfers have been authorized by the relevant party.
  Split validate_transparent_bundle into 3 functions.
  Now check that the diff between pre and post is the value balance.
  Now decode AssetTypes separately.
  Unifies `DeltaBalance` and `SignedAmount`
  Fix transparent bundle validation bug
  Fixes balances check in masp vp to allow non-masp transfers
  Fixes balance owner when token is minted
  Changelog #2690
  Refactors transparent bundle validation into a separate function. Removes unchecked operation.
  `valid_spend_descriptions_anchor` does not expect the presence of the sapling bundle anymore
  Refactors balances split
  Fixes unrecognized assets
  Refactors transparent bundle check to just compare maps
  Reworks masp vp to accept multiple transfers in a single tx
brentstone added a commit that referenced this pull request May 21, 2024
* origin/murisi+grarco/multi-tx-masp-vp-rebased2:
  Enable governance to change MASP token map.
  Moved SignedAmount into core and removed use of unchecked arithmetic.
  Use try_fold to build the ChangedBalances object.
  Created a structure for representing conversion leafs.
  Factored the accumulation code out of verify_sapling_balancing_value.
  Updated the WASM binaries.
  Extend SignedAmount to hold MASP value balance.
  Use a MASP crate that guarantees ValueSums.
  Make MASP VP accept IBC transactions.
  Ensure that all implied transfers have been authorized by the relevant party.
  Split validate_transparent_bundle into 3 functions.
  Now check that the diff between pre and post is the value balance.
  Now decode AssetTypes separately.
  Unifies `DeltaBalance` and `SignedAmount`
  Fix transparent bundle validation bug
  Fixes balances check in masp vp to allow non-masp transfers
  Fixes balance owner when token is minted
  Changelog #2690
  Refactors transparent bundle validation into a separate function. Removes unchecked operation.
  `valid_spend_descriptions_anchor` does not expect the presence of the sapling bundle anymore
  Refactors balances split
  Fixes unrecognized assets
  Refactors transparent bundle check to just compare maps
  Reworks masp vp to accept multiple transfers in a single tx
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Allow multiple transactions from masp VP
3 participants