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

Drop support for balancing transactions in eras more recent than the node tip #3923

Merged
merged 6 commits into from
May 26, 2023

Conversation

Anviking
Copy link
Member

@Anviking Anviking commented May 11, 2023

  • Always balance transactions in the era of the local node tip

Comments

Previously we used to leverage the conversion between Cardano.ProtocolParameters and Ledger.PParams era to potentially "upcast" the current protocol parameters to Ledger.PParams to a newer era.

This may have been useful for testing features in new eras on mainnet before a HF, even if the resulting txs would have been unsubmittable. Instead of doing this one can test on a public testnet, local cluster or on the unit level.

Issue Number

ADP-2990

@Anviking Anviking self-assigned this May 11, 2023
@Anviking Anviking force-pushed the anviking/ADP-2990/no-balanceTx-in-future-eras branch 8 times, most recently from 446f89f to 924ddf6 Compare May 14, 2023 17:43
@@ -179,6 +185,18 @@ cardanoTxIdeallyNoLaterThan
-> InAnyCardanoEra Cardano.Tx
cardanoTxIdeallyNoLaterThan era = unsafeCardanoTx . ideallyNoLaterThan era

-- | Re-deserialises the bytes 'SealedTx' as a transaction in the provided era
Copy link
Member Author

Choose a reason for hiding this comment

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

The whole SealedTx ugly and should probably be rethought. Perhaps using something like https://hackage.haskell.org/package/these-1.2/docs/Data-These.html

@Anviking Anviking force-pushed the anviking/ADP-2990/no-balanceTx-in-future-eras branch 4 times, most recently from 666413c to 226d906 Compare May 19, 2023 15:25
Comment on lines 1840 to 1882
data ErrWriteTxEra
= ErrOldEraNotSupported Cardano.AnyCardanoEra
| ErrTxNotInNodeEra Write.AnyRecentEra
deriving (Show, Eq)
Copy link
Member Author

Choose a reason for hiding this comment

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

Could be moved to the Write.Tx.Balance module with a function like:

data EraDependentPair f g era = EraDependentPair (f era) (g era)

chooseEraForBalancing
    :: InAnyRecentEra PParams
    -> InOneOrMoreRecentEra Tx
    -> InAnyRecentEra (PParams `EraDependentPair` Tx)
chooseEraForBalancing = undefined

and we'd want to use it if we were to provide FFI bindings for balanceTransaction.

@Anviking Anviking marked this pull request as ready for review May 19, 2023 15:29
@Anviking Anviking force-pushed the anviking/ADP-2990/no-balanceTx-in-future-eras branch from 226d906 to 1d26ef5 Compare May 22, 2023 09:55
@Anviking Anviking force-pushed the anviking/ADP-2990/no-balanceTx-in-future-eras branch from bade1dc to ac8b6e7 Compare May 23, 2023 14:12
@Anviking Anviking requested a review from Unisay May 23, 2023 14:15
@@ -89,6 +89,7 @@ data ApiErrorInfo
| BalanceTxExistingCollateral
| BalanceTxExistingKeyWitnesses
| BalanceTxExistingReturnCollateral
| TxNotInNodeEra
Copy link
Member Author

@Anviking Anviking May 23, 2023

Choose a reason for hiding this comment

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

I opted to break the pattern of BalanceTx prefixes, which I wasn't sure sure were needed.

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 it's okay for now, if we really think that this kind of error is more general than "balanceTx".

But, perhaps we should look at these API errors again in future, and clean them up a bit.

Comment on lines +3100 to +3117
parsePartialTx
:: Write.IsRecentEra era
=> Write.RecentEra era
-> Handler (Write.PartialTx era)
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
parsePartialTx
:: Write.IsRecentEra era
=> Write.RecentEra era
-> Handler (Write.PartialTx era)
parsePartialTx :: Write.IsRecentEra era => Write.RecentEra era -> Handler (Write.PartialTx era)

@@ -179,6 +185,18 @@ cardanoTxIdeallyNoLaterThan
-> InAnyCardanoEra Cardano.Tx
cardanoTxIdeallyNoLaterThan era = unsafeCardanoTx . ideallyNoLaterThan era

-- | Re-deserialises the bytes of the 'SealedTx' as a transaction in the
-- provided era, and that era only.
cardanoTxInExactEra
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd name this function unsealTransaction or unsealTx . The fact that its in the exact era is already captured by the type, so no need to express it in name.

Copy link
Member

Choose a reason for hiding this comment

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

I'd also vote for unsealTx, provided that this really is a form of "unsealing".

(The Tx shorthand is already prevalent throughout our code, so we might as well take advantage of this common shorthand.)

Copy link
Member Author

Choose a reason for hiding this comment

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

I feel this function is too weird to simply be called unsealTx plus there's symmetry with cardanoTxIdeallyNoLaterThan, so keeping.

Perhaps unsealTx will be a good name if we rethink SealedTx in the future and/or if we remove cardanoTxIdeallyNoLaterThan.

Copy link
Member

@jonathanknowles jonathanknowles left a comment

Choose a reason for hiding this comment

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

Hi @Anviking

I think the direction of this PR is great!

I just have some niggling reservations about the names of errors and the error messages: I feel that we could make the direction of time inequality a bit more explicit. What do you think? (See comments.)

apiError err403 TxNotInNodeEra $ T.unwords
[ "The provided transaction could be deserialised, just not in"
, showT era <> ","
, "the era the local node currently is in."
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
, "the era the local node currently is in."
, "the era the local node is currently in."

[ "The provided transaction could be deserialised, just not in"
, showT era <> ","
, "the era the local node currently is in."
, "If the node is not yet fully synced, try waiting."
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
, "If the node is not yet fully synced, try waiting."
, "If the node is not yet fully synchronised, try waiting."

, "If the node is not yet fully synced, try waiting."
, "If you're constructing a transaction for a future era for"
, "testing purposes, try doing so on a testnet in that era"
, "instead."
Copy link
Member

Choose a reason for hiding this comment

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

👍🏻

Nicely-written message!

One suggestion: perhaps we could transform this into a rich error, by encoding the node and transaction era as fields of the error. So something like this:

  data ApiErrorInfo
      = AddressAlreadyExists
      | ...
      | TxNotInNodeEra
+         ApiErrorTxNotInNodeEra
data ApiErrorTxNotInNodeEra = ApiErrorTxNotInNodeEra
    { eraOfNode :: !Era
    , eraOfTx   :: !Era
    }
    deriving (Data, Eq, Generic, Show, Typeable)
    deriving (FromJSON, ToJSON)
        via DefaultRecord ApiErrorTxNotInNodeEra

Comment on lines 3081 to 3085
(Write.UTxOAssumptions
genInpScripts
mScriptTemplate
(txWitnessTagFor @k)
)
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
(Write.UTxOAssumptions
genInpScripts
mScriptTemplate
(txWitnessTagFor @k)
)
(Write.UTxOAssumptions
genInpScripts
mScriptTemplate
(txWitnessTagFor @k)
)

@@ -89,6 +89,7 @@ data ApiErrorInfo
| BalanceTxExistingCollateral
| BalanceTxExistingKeyWitnesses
| BalanceTxExistingReturnCollateral
| TxNotInNodeEra
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 it's okay for now, if we really think that this kind of error is more general than "balanceTx".

But, perhaps we should look at these API errors again in future, and clean them up a bit.

Comment on lines 1841 to 1842
= ErrOldEraNotSupported Cardano.AnyCardanoEra
| ErrTxNotInNodeEra Write.AnyRecentEra
Copy link
Member

@jonathanknowles jonathanknowles May 24, 2023

Choose a reason for hiding this comment

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

How about the following names:

Suggested change
= ErrOldEraNotSupported Cardano.AnyCardanoEra
| ErrTxNotInNodeEra Write.AnyRecentEra
= ErrTxEraTooOld Cardano.AnyCardanoEra
-- ^ The transaction is from an era that is too old,
-- and no longer supported by 'balanceTransaction'.
| ErrTxEraTooNew Write.AnyRecentEra
-- ^ The transaction is from an era that is too new,
-- from the point of view of the node (at its current
-- level of synchronisation).

The thing that bugs me about the current names is that TxNotInNodeEra doesn't really make the time asymmetry clear.

My interpretation: this error can only happen if the node has not yet caught up with the transaction era: in other words, the transaction is from an era that is "too new" from the point of view of the node. Is that also your interpretation?

Copy link
Member Author

Choose a reason for hiding this comment

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

time asymmetry

No. ErrTxNotInNodeEra could currently also mean the tx is in an older era compared to the node.

For instance: if the recent eras are [Babbage, Conway], the node & pparams are in Babbage, and the supplied tx binary only is valid in [Shelley, Allegra, Mary], then 1) the node-era validation would not throw ErrOldEraNotSupported but 2) we would get a ErrTxNotInNodeEra.

Copy link
Member Author

Choose a reason for hiding this comment

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

Would be happy to discuss options to make this clearer

@@ -179,6 +185,18 @@ cardanoTxIdeallyNoLaterThan
-> InAnyCardanoEra Cardano.Tx
cardanoTxIdeallyNoLaterThan era = unsafeCardanoTx . ideallyNoLaterThan era

-- | Re-deserialises the bytes of the 'SealedTx' as a transaction in the
-- provided era, and that era only.
cardanoTxInExactEra
Copy link
Member

Choose a reason for hiding this comment

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

I'd also vote for unsealTx, provided that this really is a form of "unsealing".

(The Tx shorthand is already prevalent throughout our code, so we might as well take advantage of this common shorthand.)

properties:
message:
type: string
description: The transaction could be deserialised, just not in the era of the local node.
Copy link
Member

Choose a reason for hiding this comment

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

Further to previous comments, I wonder if it's possible to make the direction of time inequality explicit here. ^^^

(Both in the name of the error, and the description.)

For example, I'm guessing that this error cannot be produced in a situation where the node era is later than the transaction era?

]
ErrOldEraNotSupported (Cardano.AnyCardanoEra era) ->
ErrNodeNotInRecentEra (Cardano.AnyCardanoEra era) ->
apiError err403 BalanceTxEraNotSupported $ T.unwords
[ "Balancing transactions in ", showT era
Copy link
Member Author

Choose a reason for hiding this comment

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

Maybe drop "Balancing"?

@Anviking Anviking force-pushed the anviking/ADP-2990/no-balanceTx-in-future-eras branch from c5f3c35 to 1a267b7 Compare May 25, 2023 13:44
Copy link
Member

@jonathanknowles jonathanknowles left a comment

Choose a reason for hiding this comment

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

Hi @Anviking!

This PR is looking better and better!

I noticed that we currently don't test the laws for (hand-written) instances of AnyRecentEra, so I added some tests in #3958. (This PR incidentally fixes a couple of compile errors relating to unused definitions and imports.)

Also, it seems like we're missing a swagger.yaml definition for NodeNotYetInRecentEra, which was fortunately caught by the API test suite. (See comments.)

deriving (Data, Eq, Generic, Show, Typeable)
deriving (FromJSON, ToJSON)
via DefaultRecord ApiErrorNodeNotYetInRecentEra
deriving anyclass NFData
Copy link
Member

Choose a reason for hiding this comment

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

Nice! 👍🏻

Copy link
Member

Choose a reason for hiding this comment

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

However, I couldn't find an equivalent definition for NodeNotYetInRecentEra in the swagger specification.

For example, for UTxOTooSmall we have:
https://github.com/input-output-hk/cardano-wallet/blob/0a0ba43b1ed96ca3e207c75b97d6b66c2a905c59/specifications/api/swagger.yaml#L5057-L5080

Copy link
Member

@jonathanknowles jonathanknowles May 26, 2023

Choose a reason for hiding this comment

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

Luckily, this is caught by our test suite:

cardano-wallet-test-unit> Failures:
cardano-wallet-test-unit>   test/unit/Cardano/Wallet/Api/TypesSpec.hs:975:9:
cardano-wallet-test-unit>   1) Cardano.Wallet.Api.Types, Api Errors, Every ApiErrorInfo constructor has a corresponding schema type
cardano-wallet-test-unit>        Falsified (after 1 test):
cardano-wallet-test-unit>          Missing ApiErrorInfo constructors for:
cardano-wallet-test-unit>          ["NodeNotYetInRecentEra"]
cardano-wallet-test-unit>          Each of these need a corresponding swagger type of the form:
cardano-wallet-test-unit>          x-errConstructorName
cardano-wallet-test-unit>   To rerun use: --match "/Cardano.Wallet.Api.Types/Api Errors/Every ApiErrorInfo constructor has a corresponding schema type/"
cardano-wallet-test-unit> Randomized with seed 45294572

https://buildkite.com/input-output-hk/cardano-wallet/builds/25493#01885697-ddc2-47bd-845e-25c1712bb536/6-3443

]
instance Bounded AnyRecentEra where
minBound = AnyRecentEra RecentEraBabbage
maxBound = AnyRecentEra RecentEraConway
Copy link
Member

Choose a reason for hiding this comment

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

Hi @Anviking

I've added tests for the Eq, Bounded, and Enum instances in #3958.

(That PR incidentally also fixes a couple of errors relating to unused imports and function definitions.)

@jonathanknowles jonathanknowles self-requested a review May 26, 2023 08:52
Copy link
Member

@jonathanknowles jonathanknowles left a comment

Choose a reason for hiding this comment

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

Approving preemptively on the basis that we can also include in this PR:

Otherwise, LGTM!

@Anviking Anviking force-pushed the anviking/ADP-2990/no-balanceTx-in-future-eras branch 2 times, most recently from b4fa552 to f062875 Compare May 26, 2023 14:07
@Anviking
Copy link
Member Author

bors r+

iohk-bors bot added a commit that referenced this pull request May 26, 2023
3923: Drop support for balancing transactions in eras more recent than the node tip r=Anviking a=Anviking

- [x] Always balance transactions in the era of the local node tip

### Comments

Previously we used to leverage the conversion between `Cardano.ProtocolParameters` and `Ledger.PParams era` to potentially "upcast" the current protocol parameters to `Ledger.PParams` to a newer era.

This may have been useful for testing features in new eras on mainnet before a HF, even if the resulting txs would have been unsubmittable. Instead of doing this one can test on a public testnet, local cluster or on the unit level.

### Issue Number

ADP-2990

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

iohk-bors bot commented May 26, 2023

Build failed:

@Anviking
Copy link
Member Author

bors r+

iohk-bors bot added a commit that referenced this pull request May 26, 2023
3923: Drop support for balancing transactions in eras more recent than the node tip r=Anviking a=Anviking

- [x] Always balance transactions in the era of the local node tip

### Comments

Previously we used to leverage the conversion between `Cardano.ProtocolParameters` and `Ledger.PParams era` to potentially "upcast" the current protocol parameters to `Ledger.PParams` to a newer era.

This may have been useful for testing features in new eras on mainnet before a HF, even if the resulting txs would have been unsubmittable. Instead of doing this one can test on a public testnet, local cluster or on the unit level.

### Issue Number

ADP-2990

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

iohk-bors bot commented May 26, 2023

Build failed:

@Anviking Anviking force-pushed the anviking/ADP-2990/no-balanceTx-in-future-eras branch from f062875 to cdff4f6 Compare May 26, 2023 15:06
@Anviking Anviking force-pushed the anviking/ADP-2990/no-balanceTx-in-future-eras branch from cdff4f6 to a3613e8 Compare May 26, 2023 15:07
@Anviking
Copy link
Member Author

bors r+

1 similar comment
@Anviking
Copy link
Member Author

bors r+

@iohk-bors
Copy link
Contributor

iohk-bors bot commented May 26, 2023

Already running a review

@iohk-bors
Copy link
Contributor

iohk-bors bot commented May 26, 2023

Build succeeded:

@iohk-bors iohk-bors bot merged commit af82118 into master May 26, 2023
@iohk-bors iohk-bors bot deleted the anviking/ADP-2990/no-balanceTx-in-future-eras branch May 26, 2023 15:31
WilliamKingNoel-Bot pushed a commit that referenced this pull request May 26, 2023
…as more recent than the node tip r=Anviking a=Anviking - [x] Always balance transactions in the era of the local node tip ### Comments Previously we used to leverage the conversion between `Cardano.ProtocolParameters` and `Ledger.PParams era` to potentially "upcast" the current protocol parameters to `Ledger.PParams` to a newer era. This may have been useful for testing features in new eras on mainnet before a HF, even if the resulting txs would have been unsubmittable. Instead of doing this one can test on a public testnet, local cluster or on the unit level. ### Issue Number ADP-2990 Co-authored-by: Johannes Lund <[email protected]> Co-authored-by: Jonathan Knowles <[email protected]> Source commit: af82118
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.

3 participants