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

TransactionView: summary of transaction effects #4943

Merged
merged 30 commits into from
Dec 13, 2024
Merged

Conversation

TalDerei
Copy link
Collaborator

Describe your changes

References #4939

Issue ticket number and link

Checklist before requesting a review

  • I have added guiding text to explain how a reviewer should test these changes.

  • If this code contains consensus-breaking changes, I have added the "consensus-breaking" label. Otherwise, I declare my belief that there are not consensus-breaking changes, for the following reason:

@TalDerei TalDerei self-assigned this Nov 25, 2024

impl From<Balance> for pb::Balance {
fn from(_v: Balance) -> Self {
todo!() // todo: implement fallible conversion
Copy link
Collaborator Author

@TalDerei TalDerei Nov 25, 2024

Choose a reason for hiding this comment

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

comment: need to implement infallible conversion (domain type to proto)

Copy link
Collaborator Author

@TalDerei TalDerei Nov 30, 2024

Choose a reason for hiding this comment

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

filled in the implementation. Sanity check the Amount was computed properly, references from https://github.com/penumbra-zone/penumbra/blob/main/crates/core/asset/src/balance.rs#L296-L301

crates/core/transaction/src/view.rs Show resolved Hide resolved
crates/core/transaction/src/view.rs Outdated Show resolved Hide resolved
let amount = NonZeroU128::new(value.amount.into())
.ok_or_else(|| anyhow::anyhow!("amount must be non-zero"))?;

let imbalance = Imbalance::Provided(amount); // todo: fix this placeholder
Copy link
Collaborator Author

@TalDerei TalDerei Nov 25, 2024

Choose a reason for hiding this comment

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

comment: Values cannot be negative, and a negative Balance is formed by negating a balance derived from a value. How do we determine the Imbalance and differentiate between provided and required balances?

Copy link
Member

Choose a reason for hiding this comment

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

I think the modeling suggested by henry here: https://github.com/penumbra-zone/penumbra/pull/4943/files#r1855950445 takes care of that

Copy link
Collaborator Author

@TalDerei TalDerei Nov 30, 2024

Choose a reason for hiding this comment

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

the negated flag for each individual SignedValue pair now determines the imbalance

@TalDerei TalDerei marked this pull request as draft November 25, 2024 04:05
Comment on lines 95 to 100
message Balance {
// Indicates if the balance is negated.
bool negated = 1;
// Represents the vector of 'Values' in the balance.
repeated Value balance = 2;
}
Copy link
Member

Choose a reason for hiding this comment

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

xref https://github.com/penumbra-zone/penumbra/pull/4943/files#r1855748563

Since Values can't be negative, I think we'll want to have a list of pairs, each with a negation flag, something like

message Balance {
  message SignedValue {
    Value value = 1;
    bool negated = 2;
  }
  repeated SignedValue values = 1;
}

The top-level bool in the Rust Balance struct is an optimization that makes sign changes less expensive (unclear this was really necessary perf-wise, but, we have it now), IMO it should be excluded from serialization by having the serialized form always be "normalized" with individual sign bools.

Copy link
Collaborator Author

@TalDerei TalDerei Nov 30, 2024

Choose a reason for hiding this comment

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

makes sense, refactored to capture the sign information directly in the SignedValue pairs and normalize the top-level Balance

Copy link
Collaborator Author

@TalDerei TalDerei Dec 8, 2024

Choose a reason for hiding this comment

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

how should we handle cases where multiple entries share the same asset ID with different negation flags, for instance:

        let proto_balance = pb::Balance {
            values: vec![
                pb::balance::SignedValue { 
                    value: Some(pb::Value { asset_id: Some((*STAKING_TOKEN_ASSET_ID).into()), amount: Some(Amount::from(100u128).into()) }), 
                    negated: false
                },
                pb::balance::SignedValue {
                    value: Some(pb::Value {
                        asset_id: Some((*STAKING_TOKEN_ASSET_ID).into()),
                        amount: Some(Amount::from(200u128).into()),
                    }),
                    negated: true,
                },
            ],
        };

        let balance = Balance::try_from(proto_balance).expect("fallible conversion");

The BTreeMap can't hold multiple imbalances for the same asset ID. Instead, should it be doing something more sophisticated and explicitly accumulating values during conversion? Consequently, the serialized output should be

balance: Balance { required: [Value { amount: 100, asset_id: passet1984fctenw8m2fpl8a9wzguzp7j34d7vravryuhft808nyt9fdggqxmanqm }], provided: [] }

update: implemented an ordering-agnostic accumulation scheme that combines imbalances for the same asset ID.

@TalDerei TalDerei requested review from a team, erwanor and hdevalence November 30, 2024 23:17
@TalDerei TalDerei marked this pull request as ready for review November 30, 2024 23:24
@@ -11,7 +11,7 @@ use super::Address;
///
/// This type allows working with addresses and address indexes without knowing
/// the corresponding FVK.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Ord)]
Copy link
Contributor

Choose a reason for hiding this comment

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

IMO, we should explicitly write down the PartialOrd instance, so that someone refactoring the order of the enums or something doesn't accidentally change it.

Copy link
Member

@erwanor erwanor Dec 13, 2024

Choose a reason for hiding this comment

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

Good idea, is it even necessary here? if so, then I think a comment like this one:

Suggested change
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Ord)]
// Warning: This enum derives `PartialOrd` which means that re-arranging
// field-less variants is semver breaking.
#derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Ord)]

would be helpful. Can put a pin on doing a lookup on the rest of the codebase.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It's necessary to satisfy other trait bounds in accumulate_effects. I added the proposed comment

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, also we want a canonical serialization for balances.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

added PartialOrd and Ord impls for AddressView

This makes the newly added proptests pass
This matches the derived implementation, but doesn't change under
refactoring.
Signed-off-by: Erwan Or <[email protected]>
@TalDerei
Copy link
Collaborator Author

change base to release/v0.81.x?

@erwanor erwanor merged commit c654809 into main Dec 13, 2024
14 checks passed
@erwanor erwanor deleted the transaction-view-summary branch December 13, 2024 23:06
@erwanor erwanor added the protobuf-changes Makes changes to the protobuf definitions. label Dec 13, 2024
erwanor added a commit that referenced this pull request Dec 13, 2024
References #4939

- [x] I have added guiding text to explain how a reviewer should test
these changes.

- [x] If this code contains consensus-breaking changes, I have added the
"consensus-breaking" label. Otherwise, I declare my belief that there
are not consensus-breaking changes, for the following reason:

---------

Signed-off-by: Erwan Or <[email protected]>
Co-authored-by: Lucas Meier <[email protected]>
Co-authored-by: Erwan Or <[email protected]>
Co-authored-by: Erwan Or <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
protobuf-changes Makes changes to the protobuf definitions.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants