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

Generalize distributeSurplus. #3238

Merged
merged 23 commits into from
Apr 20, 2022

Conversation

jonathanknowles
Copy link
Member

@jonathanknowles jonathanknowles commented Apr 19, 2022

Issue Number

ADP-1514

Summary

This PR adjusts distributeSurplus so that:

  • It accepts a list of change outputs rather than just a single optional output.
  • It accepts change outputs of type TxOut rather than Coin.
  • It handles the responsibility of applying the fee and change deltas to the original values instead of outsourcing this responsibility to balanceTransaction.

We can say that this is a generalization of distributeSurplus, because various implementation details (for example, which change outputs are actually adjusted) are now hidden from callers behind a more general interface, for which we can state more general properties.

This also means that we can write properties that test the combination of:

  • computing the fee and change deltas
  • applying the fee and change deltas

Whereas before, we only had explicit tests for the former (computing the delta), we can now also test that:

  • The number of change outputs is always preserved.
  • The Coin fee value either stays the same or increases.
  • The Coin value within each TxOut either stays the same or increases.
  • The non-ada assets within each TxOut are not changed in any way.
  • That the deltas are applied correctly.

@jonathanknowles jonathanknowles self-assigned this Apr 19, 2022
@Anviking Anviking force-pushed the anviking/ADP-1514/distributeSurplus branch from 8248eca to 1f69c03 Compare April 19, 2022 13:14
@jonathanknowles jonathanknowles force-pushed the jonathanknowles/ADP-1514/distributeSurplus branch from 28df630 to 85f1a06 Compare April 19, 2022 13:25
@jonathanknowles jonathanknowles force-pushed the jonathanknowles/ADP-1514/distributeSurplus branch from 7064fe5 to 97e6e4f Compare April 19, 2022 13:36
Base automatically changed from anviking/ADP-1514/distributeSurplus to master April 19, 2022 15:29
The change value is of type `Maybe Coin`.

Therefore, we can also use `Just` in our comment examples.
While smaller inline properties are perfectly fine, if the definition of
the property becomes too large, then it can be come a challenge to fit
it within the horizontal line limit, resulting in code that is squished
to the right, or code that has excessive wrapping.

This commit moves the definition of an inline property to a top-level
function, giving us more horizontal space to work with. This means that
some statements no longer need to be wrapped. We can unwrap them, which
saves us vertical space.
Terms defined in `where` clauses can often be indented further to the
left than terms defined in `let` clauses. In this case, it means we no
longer need to wrap the definitions of these terms, which means we can
save vertical space, making the function more concise.

We also remove an unneeded `do`, and an unneeded `$`.
For the next few commits, we will use these container types to provide
alternative containers for change outputs in `TxFeeAndChange` in cases
where we want to indicate that we have:

- no change outputs
- exactly one change output

Later on, when we parameterize `TxFeeAndChange` further, we will remove
these types.
This function will allow us to transform values of `TxFeeAndChange`
without having to wrap and unwrap record constructors.
Before this commit, this function was only ever called with a change
value of `Nothing`, and only ever returned a change value of `Nothing`.

Therefore, we can safely replace the use of `Maybe` with `Empty`, which
only has a single `Empty` constructor. This clarifies that this function
cannot manipulate change values in any way.
This means that for a given change value c and output change delta Δc, the
following property will now hold:

>>> isJust c == isJust Δc

This transformation is safe because `balanceTransaction` treats the
following change deltas identically:

- Nothing
- Just (Coin 0)
@jonathanknowles jonathanknowles force-pushed the jonathanknowles/ADP-1514/distributeSurplus branch from 97e6e4f to 6e37e4c Compare April 20, 2022 00:31
We use the term `Delta`, because this function produces a result that is
a delta: values that must be added on to the original fee and change
outputs in order to produce the final fee and change outputs.
@jonathanknowles jonathanknowles marked this pull request as ready for review April 20, 2022 07:41
These tests cover the case where `distributeSurplus` is successful.

We also add a helper function `txOutSubtractCoin`, in the same style as
`txOutAddCoin`.
…plus`.

We add a longer comment to explain the purpose of the property.
jonathanknowles added a commit that referenced this pull request Apr 20, 2022
These types were introduced because we parameterized the **container type**
for change in `TxFeeAndChange`:

```hs
data TxFeeAndChange f = TxFeeAndChange
    { fee :: Coin
    , change :: f Coin
    }
```

This required us to instantiate `f` with types of kind `* -> *`.

But later on we parameterized the type of `change` so that it can be any type
of kind `*`:

```hs
data TxFeeAndChange change = TxFeeAndChange
    { fee :: Coin
    , change :: change
    }
```

Hence we can make the following simplifications:

  - Empty Void -> ()
  - Solo  Coin -> Coin

And therefore we can remove the `Empty` and `Solo` types.

In response to review discussion:

#3238 (comment)
jonathanknowles added a commit that referenced this pull request Apr 20, 2022
jonathanknowles added a commit that referenced this pull request Apr 20, 2022
@jonathanknowles jonathanknowles force-pushed the jonathanknowles/ADP-1514/distributeSurplus branch from b7a7add to 26829d9 Compare April 20, 2022 07:43
jonathanknowles added a commit that referenced this pull request Apr 20, 2022
These types were introduced because we parameterized the **container type**
for change in `TxFeeAndChange`:

```hs
data TxFeeAndChange f = TxFeeAndChange
    { fee :: Coin
    , change :: f Coin
    }
```

This required us to instantiate `f` with types of kind `* -> *`.

But later on we parameterized the type of `change` so that it can be any type
of kind `*`:

```hs
data TxFeeAndChange change = TxFeeAndChange
    { fee :: Coin
    , change :: change
    }
```

Hence we can make the following simplifications:

  - Empty Void -> ()
  - Solo  Coin -> Coin

And therefore we can remove the `Empty` and `Solo` types.

In response to review discussion:

#3238 (comment)
jonathanknowles added a commit that referenced this pull request Apr 20, 2022
jonathanknowles added a commit that referenced this pull request Apr 20, 2022
@jonathanknowles jonathanknowles force-pushed the jonathanknowles/ADP-1514/distributeSurplus branch from 26829d9 to 38be46b Compare April 20, 2022 07:46
These types were introduced because we parameterized the **container type**
for change in `TxFeeAndChange`:

```hs
data TxFeeAndChange f = TxFeeAndChange
    { fee :: Coin
    , change :: f Coin
    }
```

This required us to instantiate `f` with types of kind `* -> *`.

But later on we parameterized the type of `change` so that it can be any type
of kind `*`:

```hs
data TxFeeAndChange change = TxFeeAndChange
    { fee :: Coin
    , change :: change
    }
```

Hence we can make the following simplifications:

  - Empty Void -> ()
  - Solo  Coin -> Coin

And therefore we can remove the `Empty` and `Solo` types.

In response to review discussion:

#3238 (comment)
@jonathanknowles jonathanknowles force-pushed the jonathanknowles/ADP-1514/distributeSurplus branch from 38be46b to bd4b985 Compare April 20, 2022 07:47
Copy link
Member

@Anviking Anviking left a comment

Choose a reason for hiding this comment

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

lgtm, thanks!

@Anviking
Copy link
Member

bors r+

iohk-bors bot added a commit that referenced this pull request Apr 20, 2022
3238: Generalize `distributeSurplus`. r=Anviking a=jonathanknowles

## Issue Number

ADP-1514

## Summary

This PR adjusts `distributeSurplus` so that:

- It accepts a _list_ of change outputs rather than just a single _optional_ output.
- It accepts change outputs of type `TxOut` rather than `Coin`.
- It handles the responsibility of applying the `fee` and `change` deltas to the original values instead of outsourcing this responsibility to `balanceTransaction`.

We can say that this is a **_generalization_** of `distributeSurplus`, because various implementation details (for example, which change outputs are actually adjusted) are now hidden from callers behind a more general interface, for which we can state more general properties.

This also means that we can write properties that test the **_combination_** of:
- **_computing_** the fee and change deltas
- **_applying_** the fee and change deltas

Whereas before, we only had explicit tests for the former (_computing_ the delta), we can now **_also_** test that:

- The _number_ of change outputs is always preserved.
- The `Coin` `fee` value either stays the same or increases.
- The `Coin` value within each `TxOut` either stays the same or increases.
- The non-ada assets within each `TxOut` are not changed in any way.
- That the deltas are applied correctly.

Co-authored-by: Jonathan Knowles <[email protected]>
@iohk-bors
Copy link
Contributor

iohk-bors bot commented Apr 20, 2022

Canceled.

@Anviking
Copy link
Member

I pushed just a small update: efc6c13

bors r+

@iohk-bors
Copy link
Contributor

iohk-bors bot commented Apr 20, 2022

Build succeeded:

@iohk-bors iohk-bors bot merged commit 1bfbb8d into master Apr 20, 2022
@iohk-bors iohk-bors bot deleted the jonathanknowles/ADP-1514/distributeSurplus branch April 20, 2022 12:31
WilliamKingNoel-Bot pushed a commit that referenced this pull request Apr 20, 2022
paolino pushed a commit that referenced this pull request Apr 26, 2022
These types were introduced because we parameterized the **container type**
for change in `TxFeeAndChange`:

```hs
data TxFeeAndChange f = TxFeeAndChange
    { fee :: Coin
    , change :: f Coin
    }
```

This required us to instantiate `f` with types of kind `* -> *`.

But later on we parameterized the type of `change` so that it can be any type
of kind `*`:

```hs
data TxFeeAndChange change = TxFeeAndChange
    { fee :: Coin
    , change :: change
    }
```

Hence we can make the following simplifications:

  - Empty Void -> ()
  - Solo  Coin -> Coin

And therefore we can remove the `Empty` and `Solo` types.

In response to review discussion:

#3238 (comment)
paolino pushed a commit that referenced this pull request Apr 26, 2022
paolino pushed a commit that referenced this pull request Apr 26, 2022
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.

2 participants