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

Make TxBodyContent an instance of Monoid #4458

Closed

Conversation

LudvikGalois
Copy link
Contributor

TxBodyContent is now an instance of Monoid, allowing things like

foo :: TxBodyContent BuildTx BabbageEra
foo = mempty { txValidityRange = someValidityRange }

bar :: TxBodyContent BuildTx BabbageEra
bar = mempty { txIns = someTxIns, txOuts = someTxOuts }

baz :: TxBodyContent BuildTx BabbageEra
baz = mempty { txOuts = someMoreTxOuts }

transaction :: TxBodyContent BuildTx BabbageEra
transaction = mconcat [foo, bar, baz]

@LudvikGalois LudvikGalois force-pushed the ludvikgalois/transaction-body-content-monoid branch 2 times, most recently from 4ecda34 to 9977a6d Compare September 23, 2022 07:46
@LudvikGalois LudvikGalois marked this pull request as ready for review September 23, 2022 07:48
Copy link
Contributor

@Jimbo4350 Jimbo4350 left a comment

Choose a reason for hiding this comment

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

Looking good but with one comment

instance Semigroup (TxValidityLowerBound era) where
TxValidityNoLowerBound <> x = x
x <> TxValidityNoLowerBound = x
(TxValidityLowerBound wit l) <> (TxValidityLowerBound _ r) = TxValidityLowerBound wit (max l r)
Copy link
Contributor

Choose a reason for hiding this comment

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

I disagree with using max here. SlotNo has a Num instance, I think we should add the values together with (+). That way a user can adjust the validity lower bound as they see fit, with positive or negative values.

@github-actions
Copy link

This PR is stale because it has been open 45 days with no activity.

@github-actions github-actions bot added the Stale label Nov 22, 2022
@koslambrou
Copy link
Contributor

@LudvikGalois Is @Jimbo4350's comment the only thing preventing from merging this PR?

@LudvikGalois
Copy link
Contributor Author

@koslambrou I think so? I haven't come back to this because the reason I wanted it disappeared.

@koslambrou
Copy link
Contributor

koslambrou commented Nov 22, 2022

@koslambrou I think so? I haven't come back to this because the reason I wanted it disappeared.

@LudvikGalois Do you want to continue the PR or should I take over?

@github-actions github-actions bot removed the Stale label Nov 23, 2022
@newhoggy newhoggy self-assigned this Feb 28, 2023
TxBodyContent is now an instance of Monoid, allowing things like

```haskell

foo :: TxBodyContent BuildTx BabbageEra
foo = mempty { txValidityRange = someValidityRange }

bar :: TxBodyContent BuildTx BabbageEra
bar = mempty { txIns = someTxIns, txOuts = someTxOuts }

baz :: TxBodyContent BuildTx BabbageEra
baz = mempty { txOuts = someMoreTxOuts }

transaction :: TxBodyContent BuildTx BabbageEra
transaction = mconcat [foo, bar, baz]
```
instance Semigroup (TxValidityLowerBound era) where
TxValidityNoLowerBound <> x = x
x <> TxValidityNoLowerBound = x
(TxValidityLowerBound wit l) <> (TxValidityLowerBound _ r) = TxValidityLowerBound wit (max l r)
Copy link
Contributor

@newhoggy newhoggy Mar 1, 2023

Choose a reason for hiding this comment

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

The thing that bothers me is we throw away the witness on the RHS of <>. Is this 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.

Oh it's a type witness. Maybe it's okay?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is safe to do for all the "feature supported in era" type witnesses. For any given era, they have at most one non-bottom value, so it doesn't matter "which one" you pick.

…pperBoundSupportedInEra and ValidityLowerBoundSupportedInEra
@newhoggy newhoggy force-pushed the ludvikgalois/transaction-body-content-monoid branch from 9977a6d to 28f43b0 Compare March 1, 2023 06:14
@@ -13,6 +13,7 @@
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
Copy link
Contributor

Choose a reason for hiding this comment

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

We can remove the UndecidableInstances pragma with:

instance IsCardanoEra era => Monoid (TxBodyContent ViewTx era) where
  mempty = TxBodyContent
      { txIns = mempty
      , txInsCollateral = mempty
      , txInsReference = mempty
      , txOuts = mempty
      , txTotalCollateral = mempty
      , txReturnCollateral = TxReturnCollateralNone
      , txFee = mempty
      , txValidityRange = (mempty, mempty)
      , txMetadata = mempty
      , txAuxScripts = mempty
      , txExtraKeyWits = mempty
      , txProtocolParams = Nothing <$ (mempty :: BuildTxWith ViewTx ())
      , txWithdrawals = mempty
      , txCertificates = mempty
      , txUpdateProposal = TxUpdateProposalNone
      , txMintValue = mempty
      , txScriptValidity = mempty
      }
instance IsCardanoEra era => Monoid (TxBodyContent BuildTx era) where
  mempty = TxBodyContent
      { txIns = mempty
      , txInsCollateral = mempty
      , txInsReference = mempty
      , txOuts = mempty
      , txTotalCollateral = mempty
      , txReturnCollateral = TxReturnCollateralNone
      , txFee = mempty
      , txValidityRange = (mempty, mempty)
      , txMetadata = mempty
      , txAuxScripts = mempty
      , txExtraKeyWits = mempty
      , txProtocolParams = Nothing <$ (mempty :: BuildTxWith BuildTx ())
      , txWithdrawals = mempty
      , txCertificates = mempty
      , txUpdateProposal = TxUpdateProposalNone
      , txMintValue = mempty
      , txScriptValidity = mempty
      }

@newhoggy
Copy link
Contributor

newhoggy commented Mar 6, 2023

Hmm, this actually doesn't work. For example when I try to rewrite TxBodyContent to mempty here:

  dummyTx :: TxBodyContent BuildTx era
  dummyTx = TxBodyContent {
      txIns = [( TxIn "dbaff4e270cfb55612d9e2ac4658a27c79da4a5271c6f90853042d1403733810" (TxIx 0)
               , BuildTxWith $ KeyWitness KeyWitnessForSpending )]
    , txInsCollateral = TxInsCollateralNone
    , txInsReference = TxInsReferenceNone
    , txOuts = []
    , txFee = mkTxFee 0
    , txValidityRange = (TxValidityNoLowerBound, mkTxValidityUpperBound 0)
    , txMetadata = metadata
    , txAuxScripts = TxAuxScriptsNone
    , txExtraKeyWits = TxExtraKeyWitnessesNone
    , txProtocolParams = BuildTxWith Nothing
    , txWithdrawals = TxWithdrawalsNone
    , txCertificates = TxCertificatesNone
    , txUpdateProposal = TxUpdateProposalNone
    , txMintValue = TxMintNone
    , txScriptValidity = TxScriptValidityNone
    , txReturnCollateral = TxReturnCollateralNone
    , txTotalCollateral = TxTotalCollateralNone
    }

I get the error:

src/Cardano/Api/TxBody.hs:2618:5: error:
    • Ambiguous type variable ‘build0’ arising from a use of ‘mempty’
      prevents the constraint ‘(Monoid
                                  (BuildTxWith build0 ()))’ from being solved.
      Probable fix: use a type annotation to specify what ‘build0’ should be.
      These potential instances exist:
        instance Monoid a => Monoid (BuildTxWith BuildTx a)
          -- Defined at src/Cardano/Api/TxBody.hs:1207:10
        instance Semigroup a => Monoid (BuildTxWith ViewTx a)
          -- Defined at src/Cardano/Api/TxBody.hs:1204:10
    • In the expression: mempty
      In the expression:
        mempty
          {txIns = fromLedgerTxIns era body,
           txInsCollateral = fromLedgerTxInsCollateral era body,
           txInsReference = fromLedgerTxInsReference era body,
           txOuts = fromLedgerTxOuts era body scriptdata,
           txTotalCollateral = fromLedgerTxTotalCollateral era body,
           txReturnCollateral = fromLedgerTxReturnCollateral era body,
           txFee = fromLedgerTxFee era body,
           txValidityRange = fromLedgerTxValidityRange era body,
           txWithdrawals = fromLedgerTxWithdrawals era body,
           txCertificates = fromLedgerTxCertificates era body,
           txUpdateProposal = fromLedgerTxUpdateProposal era body,
           txMintValue = fromLedgerTxMintValue era body,
           txExtraKeyWits = fromLedgerTxExtraKeyWitnesses era body,
           txProtocolParams = ViewTx, txMetadata, txAuxScripts,
           txScriptValidity = scriptValidity}
      In an equation for ‘fromLedgerTxBody’:
          fromLedgerTxBody era scriptValidity body scriptdata mAux
            = mempty
                {txIns = fromLedgerTxIns era body,
                 txInsCollateral = fromLedgerTxInsCollateral era body,
                 txInsReference = fromLedgerTxInsReference era body,
                 txOuts = fromLedgerTxOuts era body scriptdata,
                 txTotalCollateral = fromLedgerTxTotalCollateral era body,
                 txReturnCollateral = fromLedgerTxReturnCollateral era body,
                 txFee = fromLedgerTxFee era body,
                 txValidityRange = fromLedgerTxValidityRange era body,
                 txWithdrawals = fromLedgerTxWithdrawals era body,
                 txCertificates = fromLedgerTxCertificates era body,
                 txUpdateProposal = fromLedgerTxUpdateProposal era body,
                 txMintValue = fromLedgerTxMintValue era body,
                 txExtraKeyWits = fromLedgerTxExtraKeyWitnesses era body,
                 txProtocolParams = ViewTx, txMetadata, txAuxScripts,
                 txScriptValidity = scriptValidity}
            where
                (txMetadata, txAuxScripts) = fromLedgerTxAuxiliaryData era mAux
     |
2618 |     mempty
     |     ^^^^^^

@newhoggy
Copy link
Contributor

newhoggy commented Mar 6, 2023

Closing this PR in favour of some other strategy. Ongoing work will be tracked by #4941

@newhoggy newhoggy closed this Mar 6, 2023
instance IsCardanoEra era => Monoid (TxValidityUpperBound era) where
mempty = case cardanoEra @era of
ByronEra -> TxValidityNoUpperBound ValidityNoUpperBoundInByronEra
ShelleyEra -> TxValidityUpperBound ValidityUpperBoundInShelleyEra maxBound
Copy link
Contributor

Choose a reason for hiding this comment

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

ShelleyEra -> TxValidityUpperBound ValidityUpperBoundInShelleyEra maxBound

Was this how it was in the original code?

Why is Shelly era special that it should use maxBound?

Copy link
Contributor

Choose a reason for hiding this comment

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

-- Note that the 'ShelleyEra' /does not support/ omitting a validity upper
-- bound. It was introduced as a /required/ field in Shelley and then made
-- optional in Allegra and subsequent eras.
--
-- The Byron era supports this by virtue of the fact that it does not support
-- validity ranges at all.

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.

4 participants