-
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
Conclude new tx workflow #3449
Conclude new tx workflow #3449
Conversation
|
||
instance ToJSON ApiSealedTxEncoding where | ||
toJSON HexEncoded = Bool True | ||
toJSON Base64Encoded = Bool False |
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.
toJSON Base64Encoded = Bool False | |
toJSON Base64Encoded = Bool False | |
newtype ApiSerialisedTransaction = ApiSerialisedTransaction | ||
{ transaction :: ApiT SealedTx | ||
{ transaction :: (ApiT SealedTx, ApiSealedTxEncoding) | ||
} deriving stock (Eq, Generic, Show) | ||
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.
data ApiSerialisedTransaction = ApiSerialisedTransaction
{ serialisedTxSealed :: ApiT SealedTx
, serialisedTxEncoding :: ApiSealedTxEncoding
} deriving stock (Eq, Generic, Show)
deriving anyclass (NFData)
I find this representation more readable at call sites because of the names of the accessor functions, as opposed to meaningless fst
/ snd
, example:
this line is less readable:
let bytes = serialisedTx $ getApiT $ fst $ (tx ^. #transaction)
than this one:
let bytes = serialisedTx $ getApiT $ serialisedTxSealed $ tx ^. #transaction
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.
sounds reasonable - done
@@ -1033,6 +1046,7 @@ data ApiValidityBound | |||
data ApiSignTransactionPostData = ApiSignTransactionPostData | |||
{ transaction :: !(ApiT SealedTx) | |||
, passphrase :: !(ApiT (Passphrase "lenient")) | |||
, hexOutput :: !(Maybe Bool) |
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.
I believe the Just
of the Maybe
is another arrow if we care about this:
import Data.Maybe.Strict (StrictMaybe (..))
:set -XStrictData
data Foo f = Foo { foo :: f Int }
λ> let !a = foo $ Foo $ Just $ undefined
λ> let !a = foo $ Foo $ SJust $ undefined
*** Exception: Prelude.undefined
CallStack (from HasCallStack):
error, called at libraries/base/GHC/Err.hs:79:14 in base:GHC.Err
undefined, called at <interactive>:76:30 in interactive:Ghci18
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.
Actually this might be the same thing as what you said, except that hexOutput :: !(Maybe !Bool)
isn't allowed?
λ> data Foo = Foo { foo :: !(Maybe (!Int)) }
<interactive>:83:34: error:
• Unexpected strictness annotation: !Int
strictness annotation cannot appear nested inside a type
• In the first argument of ‘Maybe’, namely ‘(!Int)’
In the type ‘(Maybe (!Int))’
In the definition of data constructor ‘Foo’
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.
Yes, your example demonstrates my point. StrictMaybe
is the way.
https://hackage.haskell.org/package/strict-wrapper-0.0.0.0/docs/Data-Strict-Wrapper.html is interesting lib.
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.
Alas, I don't think that we need strict fields for our Api*
data types, because these are intermediate types only used for carrying data across an interface.
If we want to control space usage, it does make sense to maintain space invariants on data types that are long-lived (such as UTxO
), but that is not the case here.
@@ -1033,6 +1046,7 @@ data ApiValidityBound | |||
data ApiSignTransactionPostData = ApiSignTransactionPostData | |||
{ transaction :: !(ApiT SealedTx) |
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.
Btw, ApiT
isn't a strict container, so !(ApiT !SealedTx)
makes more sense.
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.
As @HeinrichApfelmus explained, ApiT
is declared as a newtype
and those guys are strict by their nature. So my comment doesn't apply.
parseJSON = withBool "ApiSealedTxEncoding" $ \b -> case b of | ||
True -> pure HexEncoded | ||
False -> pure Base64Encoded |
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.
parseJSON = withBool "ApiSealedTxEncoding" $ \b -> case b of | |
True -> pure HexEncoded | |
False -> pure Base64Encoded | |
parseJSON = withBool "ApiSealedTxEncoding" $ | |
pure . bool Base64Encoded HexEncoded |
?
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'm going to call the bool
ice on bool
. 👮♂️
If you really want to get rid of the intermediate name b
, I would prefer
parseJSON = withBool "ApiSealedTxEncoding" . pure $ \case
True -> HexEncoded
False -> Base64Encoded
The explicit True
and False
is useful as this is about converting a flag into a more value with more meaning attached to it, and it's not obvious which case is which.
instance ToJSON ApiSealedTxEncoding where | ||
toJSON HexEncoded = Bool True | ||
toJSON Base64Encoded = Bool False |
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.
This instance means that ApiSealedTxEncoding
is represented as Bool
in the JSON.
I'd suggest to represent it as String
with 2 possible values "base16" and "base64".
OpenAPI supports enum
which is convenient in case like this one.
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.
sounds like a good idea - done
specifications/api/swagger.yaml
Outdated
hex_output: | ||
type: boolean | ||
default: false |
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.
hex_output: | |
type: boolean | |
default: false | |
encoding: | |
type: string | |
enum: ["base16", "base64"] |
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 would agree with making this an enum
.
@@ -2366,7 +2366,7 @@ submitTx | |||
-> [(HTTP.Status, Either RequestException ApiTxId) -> m ()] | |||
-> m ApiTxId | |||
submitTx ctx tx expectations = do | |||
let bytes = serialisedTx $ getApiT (tx ^. #transaction) | |||
let bytes = serialisedTx $ getApiT $ fst $ (tx ^. #transaction) |
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.
let bytes = serialisedTx $ getApiT $ fst $ (tx ^. #transaction) | |
let bytes = serialisedTx $ getApiT $ fst $ tx ^. #transaction |
and also fst
is not telling me anything :(
@@ -317,7 +317,7 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do | |||
Just m | |||
|
|||
let era = fromApiEra $ _mainEra ctx | |||
let tx = cardanoTxIdeallyNoLaterThan era $ getApiT (signedTx ^. #transaction) | |||
let tx = cardanoTxIdeallyNoLaterThan era $ getApiT (fst $ signedTx ^. #transaction) |
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.
let tx = cardanoTxIdeallyNoLaterThan era $ getApiT (fst $ signedTx ^. #transaction) | |
let tx = cardanoTxIdeallyNoLaterThan era $ getApiT $ fst $ signedTx ^. #transaction |
@@ -384,7 +384,7 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do | |||
Just m | |||
|
|||
let era = fromApiEra $ _mainEra ctx | |||
let tx = cardanoTxIdeallyNoLaterThan era $ getApiT (signedTx ^. #transaction) | |||
let tx = cardanoTxIdeallyNoLaterThan era $ getApiT (fst $ signedTx ^. #transaction) |
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.
let tx = cardanoTxIdeallyNoLaterThan era $ getApiT (fst $ signedTx ^. #transaction) | |
let tx = cardanoTxIdeallyNoLaterThan era $ getApiT $ fst $ signedTx ^. #transaction |
@@ -2034,8 +2035,10 @@ signTransaction ctx (ApiT wid) body = do | |||
-- TODO: The body+witnesses seem redundant with the sealedTx already. What's | |||
-- the use-case for having them provided separately? In the end, the client | |||
-- should be able to decouple them if they need to. | |||
pure $ Api.ApiSerialisedTransaction | |||
{ transaction = ApiT sealedTx' | |||
pure $ ApiSerialisedTransaction |
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.
pure $ ApiSerialisedTransaction | |
pure ApiSerialisedTransaction |
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.
Thanks Pawel! 😊 Two main points:
- Complete removal of the possibility to withdraw from external wallets (maybe in a follow-up pull request?)
- Result type
ApiConstructTransaction
— I agree with Yura's suggestion of removing the pair in favor of an additional field. Choosing a short field name would limit the impact on integration tests.
, ConstructByronTransaction | ||
, SignByronTransaction |
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.
👍
@@ -540,58 +540,6 @@ spec = describe "NEW_SHELLEY_TRANSACTIONS" $ do | |||
, expectField #withdrawals (`shouldSatisfy` (withdrawalWith External)) | |||
] | |||
|
|||
it "TRANS_NEW_CREATE_03b - Withdrawal from external wallet" $ \ctx -> runResourceT $ do |
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.
At the end of this pull request, there seems to be a mismatch between implementation and documentation: 🤔 The swagger excludes the external withdrawals from the endpoint, but the ApiConstructTransactionData
type still uses ApiWithdrawalPostData
, which means that it will happily parse withdrawals to an external wallet.
Maybe going all the way of removing support is out of scope for this pull request, but I recommend doing it in a follow-up pull request, then.
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 introduced ApiSelfWithdrawalPostData
to address this in the current PR and adjusted all code and testing
data ApiConstructTransaction (n :: NetworkDiscriminant) = ApiConstructTransaction | ||
{ transaction :: !(ApiT SealedTx) | ||
{ transaction :: !(ApiT SealedTx, ApiSealedTxEncoding) |
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.
{ transaction :: !(ApiT SealedTx, ApiSealedTxEncoding) | |
{ transaction :: ApiSerialisedTransaction |
I agree with Yura's comment on ApiSerialisedTransaction
here.
The many pattern matches
let (txCbor,_) = getFromResponse #transaction rTx
can be avoided in favor of extracting a subfield,
let txCbor = getFromResponse (#transaction . #sealedTx) rTx
or something like that. One could even use Quantity
, but I don't want to drag that type into this.
specifications/api/swagger.yaml
Outdated
hex_output: | ||
type: boolean | ||
default: false |
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 would agree with making this an enum
.
@@ -1033,6 +1046,7 @@ data ApiValidityBound | |||
data ApiSignTransactionPostData = ApiSignTransactionPostData | |||
{ transaction :: !(ApiT SealedTx) | |||
, passphrase :: !(ApiT (Passphrase "lenient")) | |||
, hexOutput :: !(Maybe Bool) |
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.
Alas, I don't think that we need strict fields for our Api*
data types, because these are intermediate types only used for carrying data across an interface.
If we want to control space usage, it does make sense to maintain space invariants on data types that are long-lived (such as UTxO
), but that is not the case here.
752b5de
to
c52d97c
Compare
c52d97c
to
3918890
Compare
bors r+ |
3449: Conclude new tx workflow r=paweljakubas a=paweljakubas <!-- Detail in a few bullet points the work accomplished in this PR. Before you submit, don't forget to: * Make sure the GitHub PR fields are correct: ✓ Set a good Title for your PR. ✓ Assign yourself to the PR. ✓ Assign one or more reviewer(s). ✓ Link to a Jira issue, and/or other GitHub issues or PRs. ✓ In the PR description delete any empty sections and all text commented in <!--, so that this text does not appear in merge commit messages. * Don't waste reviewers' time: ✓ If it's a draft, select the Create Draft PR option. ✓ Self-review your changes to make sure nothing unexpected slipped through. * Try to make your intent clear: ✓ Write a good Description that explains what this PR is meant to do. ✓ Jira will detect and link to this PR once created, but you can also link this PR in the description of the corresponding Jira ticket. ✓ Highlight what Testing you have done. ✓ Acknowledge any changes required to the Documentation. --> - [x] Removing byron things - [x] Cleaning ApiAddressDestination - [x] Foreign withdrawals not supported hence test removed - [x] added support in constructTx, signTx and balanceTx for producing serialized tx in either hex or base64 (this one is default) We accept in decodeTx, signTx, balanceTx and submitTx both format and for the sake of comparison and interoperability (with for example cardano-cli) it seems like a good idea. The consequence: in each POST we have OPTIONAL "hex_output" field which is set to true means requesting hex-encoded output. - [x] regenerated golden tests - [x] added proof of operability in integration testing - [x] updated swagger ### Comments <!-- Additional comments, links, or screenshots to attach, if any. --> ### Issue Number adp-2083 <!-- Reference the Jira/GitHub issue that this PR relates to, and which requirements it tackles. Note: Jira issues of the form ADP- will be auto-linked. --> Co-authored-by: Pawel Jakubas <[email protected]>
Build failed: #expected hlint |
bors r+ |
3449: Conclude new tx workflow r=paweljakubas a=paweljakubas <!-- Detail in a few bullet points the work accomplished in this PR. Before you submit, don't forget to: * Make sure the GitHub PR fields are correct: ✓ Set a good Title for your PR. ✓ Assign yourself to the PR. ✓ Assign one or more reviewer(s). ✓ Link to a Jira issue, and/or other GitHub issues or PRs. ✓ In the PR description delete any empty sections and all text commented in <!--, so that this text does not appear in merge commit messages. * Don't waste reviewers' time: ✓ If it's a draft, select the Create Draft PR option. ✓ Self-review your changes to make sure nothing unexpected slipped through. * Try to make your intent clear: ✓ Write a good Description that explains what this PR is meant to do. ✓ Jira will detect and link to this PR once created, but you can also link this PR in the description of the corresponding Jira ticket. ✓ Highlight what Testing you have done. ✓ Acknowledge any changes required to the Documentation. --> - [x] Removing byron things - [x] Cleaning ApiAddressDestination - [x] Foreign withdrawals not supported hence test removed - [x] added support in constructTx, signTx and balanceTx for producing serialized tx in either hex or base64 (this one is default) We accept in decodeTx, signTx, balanceTx and submitTx both format and for the sake of comparison and interoperability (with for example cardano-cli) it seems like a good idea. The consequence: in each POST we have OPTIONAL "hex_output" field which is set to true means requesting hex-encoded output. - [x] regenerated golden tests - [x] added proof of operability in integration testing - [x] updated swagger ### Comments <!-- Additional comments, links, or screenshots to attach, if any. --> ### Issue Number adp-2083 <!-- Reference the Jira/GitHub issue that this PR relates to, and which requirements it tackles. Note: Jira issues of the form ADP- will be auto-linked. --> Co-authored-by: Pawel Jakubas <[email protected]>
Build failed:
|
bors r+ |
3449: Conclude new tx workflow r=paweljakubas a=paweljakubas <!-- Detail in a few bullet points the work accomplished in this PR. Before you submit, don't forget to: * Make sure the GitHub PR fields are correct: ✓ Set a good Title for your PR. ✓ Assign yourself to the PR. ✓ Assign one or more reviewer(s). ✓ Link to a Jira issue, and/or other GitHub issues or PRs. ✓ In the PR description delete any empty sections and all text commented in <!--, so that this text does not appear in merge commit messages. * Don't waste reviewers' time: ✓ If it's a draft, select the Create Draft PR option. ✓ Self-review your changes to make sure nothing unexpected slipped through. * Try to make your intent clear: ✓ Write a good Description that explains what this PR is meant to do. ✓ Jira will detect and link to this PR once created, but you can also link this PR in the description of the corresponding Jira ticket. ✓ Highlight what Testing you have done. ✓ Acknowledge any changes required to the Documentation. --> - [x] Removing byron things - [x] Cleaning ApiAddressDestination - [x] Foreign withdrawals not supported hence test removed - [x] added support in constructTx, signTx and balanceTx for producing serialized tx in either hex or base64 (this one is default) We accept in decodeTx, signTx, balanceTx and submitTx both format and for the sake of comparison and interoperability (with for example cardano-cli) it seems like a good idea. The consequence: in each POST we have OPTIONAL "hex_output" field which is set to true means requesting hex-encoded output. - [x] regenerated golden tests - [x] added proof of operability in integration testing - [x] updated swagger ### Comments <!-- Additional comments, links, or screenshots to attach, if any. --> ### Issue Number adp-2083 <!-- Reference the Jira/GitHub issue that this PR relates to, and which requirements it tackles. Note: Jira issues of the form ADP- will be auto-linked. --> Co-authored-by: Pawel Jakubas <[email protected]>
Build failed:
Interesting... Searching for "Applied {1,0}" it seems the pool worker saw blocks, but no wallet? 🥴 |
bors retry |
Build succeeded: |
We accept in decodeTx, signTx, balanceTx and submitTx both format and for the sake of comparison and interoperability
(with for example cardano-cli) it seems like a good idea. The consequence: in each POST we have OPTIONAL
"hex_output" field which is set to true means requesting hex-encoded output.
Comments
Issue Number
adp-2083