-
Notifications
You must be signed in to change notification settings - Fork 217
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
Drop support for balancing transactions in eras more recent than the node tip #3923
Conversation
446f89f
to
924ddf6
Compare
@@ -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 |
There was a problem hiding this comment.
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
666413c
to
226d906
Compare
lib/wallet/src/Cardano/Wallet.hs
Outdated
data ErrWriteTxEra | ||
= ErrOldEraNotSupported Cardano.AnyCardanoEra | ||
| ErrTxNotInNodeEra Write.AnyRecentEra | ||
deriving (Show, Eq) |
There was a problem hiding this comment.
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
.
226d906
to
1d26ef5
Compare
bade1dc
to
ac8b6e7
Compare
@@ -89,6 +89,7 @@ data ApiErrorInfo | |||
| BalanceTxExistingCollateral | |||
| BalanceTxExistingKeyWitnesses | |||
| BalanceTxExistingReturnCollateral | |||
| TxNotInNodeEra |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
parsePartialTx | ||
:: Write.IsRecentEra era | ||
=> Write.RecentEra era | ||
-> Handler (Write.PartialTx era) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.)
There was a problem hiding this comment.
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
.
There was a problem hiding this 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." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
, "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." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
, "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." |
There was a problem hiding this comment.
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
(Write.UTxOAssumptions | ||
genInpScripts | ||
mScriptTemplate | ||
(txWitnessTagFor @k) | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Write.UTxOAssumptions | |
genInpScripts | |
mScriptTemplate | |
(txWitnessTagFor @k) | |
) | |
(Write.UTxOAssumptions | |
genInpScripts | |
mScriptTemplate | |
(txWitnessTagFor @k) | |
) |
@@ -89,6 +89,7 @@ data ApiErrorInfo | |||
| BalanceTxExistingCollateral | |||
| BalanceTxExistingKeyWitnesses | |||
| BalanceTxExistingReturnCollateral | |||
| TxNotInNodeEra |
There was a problem hiding this comment.
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.
lib/wallet/src/Cardano/Wallet.hs
Outdated
= ErrOldEraNotSupported Cardano.AnyCardanoEra | ||
| ErrTxNotInNodeEra Write.AnyRecentEra |
There was a problem hiding this comment.
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:
= 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?
There was a problem hiding this comment.
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
.
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe drop "Balancing"?
c5f3c35
to
1a267b7
Compare
There was a problem hiding this 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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! 👍🏻
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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
] | ||
instance Bounded AnyRecentEra where | ||
minBound = AnyRecentEra RecentEraBabbage | ||
maxBound = AnyRecentEra RecentEraConway |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this 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:
- property tests as included in Test class laws for
AnyRecentEra
. #3958 - a complete swagger specification for the
NodeNotYetInRecentEra
error.
Otherwise, LGTM!
b4fa552
to
f062875
Compare
bors r+ |
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]>
Build failed: |
bors r+ |
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]>
Build failed: |
f062875
to
cdff4f6
Compare
cdff4f6
to
a3613e8
Compare
bors r+ |
1 similar comment
bors r+ |
Already running a review |
Build succeeded: |
…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
Comments
Previously we used to leverage the conversion between
Cardano.ProtocolParameters
andLedger.PParams era
to potentially "upcast" the current protocol parameters toLedger.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