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

Improved validity range handling #332

Merged
merged 7 commits into from Oct 23, 2023

Conversation

newhoggy
Copy link
Collaborator

@newhoggy newhoggy commented Oct 20, 2023

Changelog

- description: |
    Split the `txValidityRange` field into two fields.
    New function `allegraEraOnwardsToByronAndAllegraOnwardsEra`
# uncomment types applicable to the change:
  type:
  # - feature        # introduces a new feature
  - breaking       # the API has changed in a breaking way
  # - compatible     # the API has changed but is non-breaking
  # - optimisation   # measurable performance improvements
  - improvement    # QoL changes e.g. refactoring
  # - bugfix         # fixes a defect
  # - test           # fixes/modifies tests
  # - maintenance    # not directly related to the code
  # - release        # related to a new release preparation
  # - documentation  # change in code docs, haddocks...

Context

Split the txValidityRange field into two fields. The two values are represented in the field as two parts to a tuple which makes it irregular and unwieldy.

Ledger groups them together but we don't necessarily need to follow what the ledger does and in any case the ledger does not use a tuple to do the grouping.

How to trust this PR

Highlight important bits of the PR that will make the review faster. If there are commands the reviewer can run to observe the new behavior, describe them.

Checklist

  • Commit sequence broadly makes sense and commits have useful messages
  • New tests are added if needed and existing tests are updated. See Running tests for more details
  • Self-reviewed the diff

@newhoggy newhoggy force-pushed the newhoggy/improved-validity-range-handling branch 2 times, most recently from 64b9bad to 6faa2e1 Compare October 20, 2023 13:02
genTxValidityRange era =
(,)
<$> genTxValidityLowerBound era
<*> genTxValidityUpperBound era
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Without tupling, we no longer need this generator.

-> TxValidityUpperBound era

TxValidityUpperBound
:: ShelleyBasedEra era
-> SlotNo
-> Maybe SlotNo
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is slightly closer the to ledger representation since the ledger uses SMaybe SlotNo.

TxValidityNoUpperBound simplifies to ByronEraOnly because it is no longer used to represent no bounds set for Shelley onwards. Instead TxValidityUpperBound Nothing serves this purpose instead.

txValidityRange :: (TxValidityLowerBound era,
TxValidityUpperBound era),
txValidityLowerBound :: TxValidityLowerBound era,
txValidityUpperBound :: TxValidityUpperBound era,
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is the core of the PR. We are splitting this field into to make TxBodyContent more regular.

@@ -1837,15 +1840,11 @@ createTransactionBody sbe txBodyContent =
in case sbe of
ShelleyBasedEraShelley -> do
update <- convTxUpdateProposal sbe (txUpdateProposal txBodyContent)
let (_, upperBound) = txValidityRange txBodyContent
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Notice also how the old code retrieves both the lower and upper bounds then throws away the lower bound. This no longer happens in the new code. We just retrieve what we need and throw nothing away.

@@ -1818,7 +1822,6 @@ createTransactionBody sbe txBodyContent =
certs = convCertificates sbe $ txCertificates txBodyContent
txAuxData = toAuxiliaryData sbe (txMetadata txBodyContent) (txAuxScripts txBodyContent)
scripts = convScripts apiScriptWitnesses
validityInterval = convValidityInterval $ txValidityRange txBodyContent
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is duplication. We call txValidityRange here and then later again here: https://github.com/input-output-hk/cardano-api/pull/332/files#r1366954769

--
-- 'invalidHereAfterTxBodyL' lens over both with a 'Maybe SlotNo' type representation. Withing the
-- Shelley era, setting Nothing will set the ttl to 'maxBound' in the underlying ledger type.
invalidHereAfterTxBodyL :: ShelleyBasedEra era -> Lens' (L.TxBody (ShelleyLedgerEra era)) (Maybe SlotNo)
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This compatibility lens allows us to treat the upper bound the same in the shelley era and subsequent eras.

& L.ttlTxBodyL .~ ttl
& L.updateTxBodyL .~ update
& L.certsTxBodyL .~ certs
& L.invalidHereAfterTxBodyL sbe .~ convValidityUpperBound sbe (txValidityUpperBound txBodyContent)
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

In the Shelley era we set the upper bound just as we do in subsequent eras thanks to this lens: https://github.com/input-output-hk/cardano-api/pull/332/files#r1366957308

Nothing -> TxValidityNoLowerBound
Just s -> TxValidityLowerBound w s
)
sbe
Copy link
Collaborator Author

@newhoggy newhoggy Oct 20, 2023

Choose a reason for hiding this comment

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

Using eons and the split of the validity range tuple, we can reduce a large case expression into a two small functions above and below.

Copy link
Contributor

Choose a reason for hiding this comment

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

That's a win!

& L.updateTxBodyL .~ update
& L.ttlTxBodyL .~ case upperBound of
TxValidityNoUpperBound era' -> case era' of {}
TxValidityUpperBound _ ttl -> ttl
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Adhoc case matching and Shelley era specific code eliminated.

& L.certsTxBodyL .~ certs
& L.updateTxBodyL .~ update
& L.invalidBeforeTxBodyL aOn .~ convValidityLowerBound (txValidityLowerBound txBodyContent)
& L.invalidHereAfterTxBodyL sbe .~ convValidityUpperBound sbe (txValidityUpperBound txBodyContent)
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The above two lens required a eon each. This will in a separate PR serve to help reduce the amount of code by allowing the large case expression in this function to be eliminated.

@@ -1857,12 +1856,15 @@ createTransactionBody sbe txBodyContent =
apiScriptValidity

ShelleyBasedEraAllegra -> do
let aOn = AllegraEraOnwardsAllegra
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Some additional lines to define the eon witness. These are hard coded currently because we still have the large case expression over sbe. When the case expression is eliminated, this will disappear.

Copy link
Contributor

@carlhammann carlhammann left a comment

Choose a reason for hiding this comment

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

I don't feel qualified to approve this, but since @carbolymer has already done so, I'm only leaving a few comments.

@@ -241,6 +242,16 @@ shelleyToAlonzoEraToShelleyToBabbageEra = \case
ShelleyToAlonzoEraMary -> ShelleyToBabbageEraMary
ShelleyToAlonzoEraAlonzo -> ShelleyToBabbageEraAlonzo

allegraEraOnwardsToByronAndAllegraOnwardsEra :: ()
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't see this being used anywhere?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

You are right in that it isn't used. I had intended to use it but later opted to do it differently instead. The function is still potentially useful.

Copy link
Contributor

Choose a reason for hiding this comment

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

We should not be adding more Eon related code. We are moving away from this.


import Lens.Micro

strictMaybeL :: Lens' (StrictMaybe a) (Maybe a)
Copy link
Contributor

Choose a reason for hiding this comment

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

This is an Iso, but microlens doesn't have such a type. Why are we using microlens?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I don't have the background to that decision unfortunately.

Copy link
Contributor

Choose a reason for hiding this comment

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

The reason I heard is that microlens is much lighter which shortens compilation time. I don't know if there are any other.

Comment on lines 35 to 38
s SNothing Nothing = SNothing
s SNothing (Just x) = SJust x
s (SJust _) Nothing = SNothing
s (SJust _) (Just x) = SJust x
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
s SNothing Nothing = SNothing
s SNothing (Just x) = SJust x
s (SJust _) Nothing = SNothing
s (SJust _) (Just x) = SJust x
s _ Nothing = SNothing
s _ (Just x) = SJust x

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Thanks for the simplification. I took it further and did this:

s _ = maybe SNothing SJust

Nothing -> TxValidityNoLowerBound
Just s -> TxValidityLowerBound w s
)
sbe
Copy link
Contributor

Choose a reason for hiding this comment

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

That's a win!

@@ -1301,8 +1302,11 @@ setTxReturnCollateral v txBodyContent = txBodyContent { txReturnCollateral = v }
setTxFee :: TxFee era -> TxBodyContent build era -> TxBodyContent build era
setTxFee v txBodyContent = txBodyContent { txFee = v }

setTxValidityRange :: (TxValidityLowerBound era, TxValidityUpperBound era) -> TxBodyContent build era -> TxBodyContent build era
setTxValidityRange v txBodyContent = txBodyContent { txValidityRange = v }
setTxValidityLowerBound :: TxValidityLowerBound era -> TxBodyContent build era -> TxBodyContent build era
Copy link
Contributor

Choose a reason for hiding this comment

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

I know this and the other functions are here for completeness, but I don't see them being used. What's your opinion on using (automatically generated) lenses here as well?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I'd like to avoid anything that involves Template Haskell, but I'm partial to generic-lens.

@newhoggy newhoggy force-pushed the newhoggy/improved-validity-range-handling branch from 6faa2e1 to 69464d4 Compare October 23, 2023 12:26
@newhoggy newhoggy added this pull request to the merge queue Oct 23, 2023
Merged via the queue into main with commit 807342e Oct 23, 2023
20 checks passed
@newhoggy newhoggy deleted the newhoggy/improved-validity-range-handling branch October 23, 2023 13:10
newhoggy pushed a commit that referenced this pull request Mar 11, 2024
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.

None yet

4 participants