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

Join drep endpoint #4693

Merged
merged 19 commits into from
Aug 5, 2024
Merged

Conversation

paweljakubas
Copy link
Contributor

@paweljakubas paweljakubas commented Jul 19, 2024

  • Swagger updated
  • Api scaffolding, Api types, Api errors
  • Adding Http.Shelley.Server joinDRep
  • Adding IO Deleg functions
  • Adding Delegation's guard
  • Checking that error is emitted when used in Babbage
  • Checking we can vote, re-vote and emit error when voting the same in the absence of pool delegation in Conway
  • Checking we can vote, re-vote and emit error when voting the same in the presence of pool delegation in Conway

Comments

Issue Number

adp-3383

@paweljakubas paweljakubas self-assigned this Jul 19, 2024
@paweljakubas paweljakubas marked this pull request as ready for review July 19, 2024 17:37
Copy link
Contributor

@HeinrichApfelmus HeinrichApfelmus left a comment

Choose a reason for hiding this comment

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

Thank you! 😊

The functionality seems to work, but I request a different separation of concerns for the modules Cardano.Wallet.Delegation and Cardano.Wallet.IO.Delegation.

Comment on lines 550 to 577
handleVoteRequest
:: WalletLayer IO s
-> DRep
-> IO Tx.VotingAction
handleVoteRequest ctx drep = do
(vAction, votingRequest) <- voteAction ctx drep
(Write.PParamsInAnyRecentEra era _, _)
<- W.readNodeTipStateForTxWrite netLayer

either (throwIO . ExceptionVoting) pure
(WD.guardOnlyVoting era $ toDrepEnriched votingRequest)
pure vAction
where
toDrepEnriched NotVotedYet = Nothing
toDrepEnriched VotedSameAsBefore = Just (True, drep)
toDrepEnriched VotedDifferently = Just (False, drep)

netLayer = ctx ^. networkLayer
Copy link
Contributor

Choose a reason for hiding this comment

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

This function is okay, but harder to understand than necessary — in particular, it's not clear what exactly toDrepEnrichted is supposed to be doing. Could you remove this function (handleVoteRequest) and structure the function joinDRep similar to the function quitStakePool instead?

In other words, I would like you to structure the code in the following way:

joinDRep  IO, collects relevant parameter values, calls

    joinDRepVotingAction  IO, provides additional parameter values (if necessary), calls

        WD.joinDRepVotingAction  *pure*, computes a result based on all parameter values.

The idea is that the functions joinDRep and joinDRepVotingAction are responsible for providing sufficient parameter values to compute the result, but the actual computation of the result (= the Either ErrCannotJoin Tx.VotingAction is contained within the pure function. In other words, the concern of figuring out what the vote action should be — if any — should be entirely confined to the definition of the pure function WD.joinDRepVotingAction.

In contrast, at the moment, this function uses toDRepEnriched to package some intermediate computation and hands it off to the function WD.guardOnlyVoting in a different module, but the meaning of the intermediate data format Maybe (Bool, DRep) is not apparent from the type signatures and function names. The logic becomes much clear if:

  • Use pure functions to compute the result.
  • Keep the computation of the result to a single module

Could you change this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

sounds reasonable! done

@paweljakubas paweljakubas force-pushed the paweljakubas/adp-3383/join-drep-endpoint branch from 7883d9d to 9aec031 Compare August 1, 2024 14:33
@paweljakubas paweljakubas force-pushed the paweljakubas/adp-3383/join-drep-endpoint branch 3 times, most recently from 9078527 to ff52060 Compare August 2, 2024 15:21
Copy link
Contributor

@HeinrichApfelmus HeinrichApfelmus left a comment

Choose a reason for hiding this comment

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

Thank you! 😊

With the improved separation of concerns for joinDRep, we can now perform a further simplification in Cardano.Wallet.Delegation — good to merge after that.

(In principle, the same considerations apply to the Cardano.Wallet.IO.Delegation.joinStakePool function, but let's leave this for a future pull request when we need to touch this area of the code again.)

Comment on lines 221 to 258
guardOnlyVoting
:: Write.IsRecentEra era
=> Write.RecentEra era
-> (Bool,DRep)
-> Either ErrCannotVote ()
guardOnlyVoting era votingSameAgain = do
when (fst votingSameAgain) $
Left $ ErrAlreadyVoted $ snd votingSameAgain

case era of
Write.RecentEraBabbage ->
Left ErrWrongEra
Write.RecentEraConway ->
Right ()

joinDRepVotingAction
:: Write.IsRecentEra era
=> Write.RecentEra era
-> DRep
-> W.WalletDelegation
-> Bool
-> Either ErrCannotVote Tx.VotingAction
joinDRepVotingAction era action dlg stakeKeyIsRegistered =
second (const vAction) $ guardOnlyVoting era votingRequest
where
isDRepSame (W.Voting drep) = drep == action
isDRepSame (W.DelegatingVoting _ drep) = drep == action
isDRepSame _ = False

isSameNext (W.WalletDelegationNext _ deleg) = isDRepSame deleg

sameWalletDelegation (W.WalletDelegation current coming) =
isDRepSame current || any isSameNext coming

(vAction, votingRequest) =
if stakeKeyIsRegistered
then (Tx.Vote action, (sameWalletDelegation dlg, action))
else (Tx.VoteRegisteringKey action, (sameWalletDelegation dlg,action))
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
guardOnlyVoting
:: Write.IsRecentEra era
=> Write.RecentEra era
-> (Bool,DRep)
-> Either ErrCannotVote ()
guardOnlyVoting era votingSameAgain = do
when (fst votingSameAgain) $
Left $ ErrAlreadyVoted $ snd votingSameAgain
case era of
Write.RecentEraBabbage ->
Left ErrWrongEra
Write.RecentEraConway ->
Right ()
joinDRepVotingAction
:: Write.IsRecentEra era
=> Write.RecentEra era
-> DRep
-> W.WalletDelegation
-> Bool
-> Either ErrCannotVote Tx.VotingAction
joinDRepVotingAction era action dlg stakeKeyIsRegistered =
second (const vAction) $ guardOnlyVoting era votingRequest
where
isDRepSame (W.Voting drep) = drep == action
isDRepSame (W.DelegatingVoting _ drep) = drep == action
isDRepSame _ = False
isSameNext (W.WalletDelegationNext _ deleg) = isDRepSame deleg
sameWalletDelegation (W.WalletDelegation current coming) =
isDRepSame current || any isSameNext coming
(vAction, votingRequest) =
if stakeKeyIsRegistered
then (Tx.Vote action, (sameWalletDelegation dlg, action))
else (Tx.VoteRegisteringKey action, (sameWalletDelegation dlg,action))
joinDRepVotingAction
:: Write.IsRecentEra era
=> Write.RecentEra era
-> DRep
-> W.WalletDelegation
-> Bool
-> Either ErrCannotVote Tx.VotingAction
joinDRepVotingAction era targetDRep dlg stakeKeyIsRegistered = do
guardEraIsConway era
when (sameWalletDelegation dlg) $
Left $ ErrAlreadyVoted $ targetDRep
pure votingAction
where
isDRepSame (W.Voting drep) = drep == targetDRep
isDRepSame (W.DelegatingVoting _ drep) = drep == targetDRep
isDRepSame _ = False
isSameNext (W.WalletDelegationNext _ deleg) = isDRepSame deleg
sameWalletDelegation (W.WalletDelegation current coming) =
isDRepSame current || any isSameNext coming
guardEraIsConway Write.RecentEraBabbage = Left WrongEra
guardEraIsConway Write.RecentEraConway = Right ()
votingAction =
if stakeKeyIsRegistered
then Tx.Vote targetDRep
else Tx.VoteRegisteringKey targetDRep

… and after separating the concerns into a single, we can now merge the definitions of the two functions and get rid of the (Bool,DRep) intermediate type while also making the logic more clear. 🤓

Copy link
Contributor Author

Choose a reason for hiding this comment

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

good hint. Done!

@paweljakubas paweljakubas force-pushed the paweljakubas/adp-3383/join-drep-endpoint branch from ff52060 to f642da2 Compare August 5, 2024 11:09
@paweljakubas paweljakubas added this pull request to the merge queue Aug 5, 2024
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Aug 5, 2024
@paweljakubas paweljakubas added this pull request to the merge queue Aug 5, 2024
Merged via the queue into master with commit 8fb09f4 Aug 5, 2024
23 checks passed
@paweljakubas paweljakubas deleted the paweljakubas/adp-3383/join-drep-endpoint branch August 5, 2024 13:15
WilliamKingNoel-Bot pushed a commit that referenced this pull request Aug 5, 2024
…he work accomplished in this PR. Before you submit, don't forget to: CODE-OF-CONDUCT.md CONTRIBUTING.md LICENSE MAINTAINERS.md README.md cabal.project configs docker-compose.yml docs flake.lock flake.nix floskell.json fourmolu.yaml hie-direnv.yaml justfile lib nix prototypes reports run scripts specifications test touch.me.CI weeder.dhall 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. CODE-OF-CONDUCT.md CONTRIBUTING.md LICENSE MAINTAINERS.md README.md cabal.project configs docker-compose.yml docs flake.lock flake.nix floskell.json fourmolu.yaml hie-direnv.yaml justfile lib nix prototypes reports run scripts specifications test touch.me.CI weeder.dhall 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. CODE-OF-CONDUCT.md CONTRIBUTING.md LICENSE MAINTAINERS.md README.md cabal.project configs docker-compose.yml docs flake.lock flake.nix floskell.json fourmolu.yaml hie-direnv.yaml justfile lib nix prototypes reports run scripts specifications test touch.me.CI weeder.dhall 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] Swagger updated - [x] Api scaffolding, Api types, Api errors - [x] Adding Http.Shelley.Server joinDRep - [x] Adding IO Deleg functions - [x] Adding Delegation's guard - [x] Checking that error is emitted when used in Babbage - [x] Checking we can vote, re-vote and emit error when voting the same in the absence of pool delegation in Conway - [x] Checking we can vote, re-vote and emit error when voting the same in the presence of pool delegation in Conway ### Comments <!-- Additional comments, links, or screenshots to attach, if any. --> ### Issue Number adp-3383 <!-- 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. --> Source commit: 8fb09f4
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.

2 participants