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

Withdrawals in multisig #3925

Merged
merged 25 commits into from
May 31, 2023
Merged

Conversation

paweljakubas
Copy link
Contributor

@paweljakubas paweljakubas commented May 11, 2023

  • Added withdrawal support for multisig
  • Added withdrawal integration test
  • Added quit integration test
  • Make sure getTransaction exposes certificates - shown in integration testing

Comments

Issue Number

adp-2604

@paweljakubas paweljakubas self-assigned this May 11, 2023
@paweljakubas paweljakubas mentioned this pull request May 11, 2023
1 task
@paweljakubas paweljakubas force-pushed the paweljakubas/adp-2604/withdrawals-in-multisig branch 3 times, most recently from d7d4636 to d21e220 Compare May 23, 2023 12:44
@paweljakubas paweljakubas marked this pull request as ready for review May 23, 2023 12:50
>>= flip verify
[ expectField
(#balance . #reward)
(`shouldBe` (Quantity 0))
Copy link
Contributor

Choose a reason for hiding this comment

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

We should probably add a check that we have some rewards before withdrawing them.

Copy link
Contributor Author

@paweljakubas paweljakubas May 23, 2023

Choose a reason for hiding this comment

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

This is checked before withdrawal and after withdrawal (should be zero as you underlined above):

1986         eventually "party1: Wallet gets rewards from pool1" $ do                                                                                                                                              
1987             r <- request @ApiWallet ctx (Link.getWallet @'Shared party1) Default Empty                                                                                                                        
1988             verify r                                                                                                                                                                                          
1989                 [ expectField                                                                                                                                                                                 
1990                       (#balance . #reward)                                                                                                                                                                    
1991                       (.> (Quantity 0))                                                                                                                                                                       
1992                 ]                                                                                                                                                                                             
1993         eventually "party2: Wallet gets rewards from pool1" $ do                                                                                                                                              
1994             r <- request @ApiWallet ctx (Link.getWallet @'Shared party2) Default Empty                                                                                                                        
1995             verify r                                                                                                                                                                                          
1996                 [ expectField                                                                                                                                                                                 
1997                       (#balance . #reward)                                                                                                                                                                    
1998                       (.> (Quantity 0))                                                                                                                                                                       
1999                 ]

Comment on lines 690 to 692
[ "I couldn't read a reward account which is required for "
, "withdrawals. Either there is db malfunction or withdrawals "
, "was used for shared wallets missing delegation template."
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
[ "I couldn't read a reward account which is required for "
, "withdrawals. Either there is db malfunction or withdrawals "
, "was used for shared wallets missing delegation template."
[ "Unable to read the reward account required for withdrawals. "
, "It appears that the withdrawals feature was utilized for a shared wallet "
, "without the corresponding delegation template."

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

Comment on lines 696 to 733
[ "It is regrettable but you've just attempted an operation "
, "that is invalid for this type of wallet. Only new 'Shelley' and "
, "'Shared' wallets can do something with rewards and this one isn't."
]
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
[ "It is regrettable but you've just attempted an operation "
, "that is invalid for this type of wallet. Only new 'Shelley' and "
, "'Shared' wallets can do something with rewards and this one isn't."
]
[ "It is regrettable but you've just attempted an operation "
, "that is invalid for this type of wallet. Only new 'Shelley' and "
, "'Shared' wallets have the capability to perform actions with rewards, "
, "which is not applicable to the current wallet."
]

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@paweljakubas
Copy link
Contributor Author

bors try

iohk-bors bot added a commit that referenced this pull request May 23, 2023
@iohk-bors
Copy link
Contributor

iohk-bors bot commented May 23, 2023

try

Build failed:

@paweljakubas paweljakubas force-pushed the paweljakubas/adp-2604/withdrawals-in-multisig branch from 0784414 to c55c61c Compare May 24, 2023 10:34
@paweljakubas
Copy link
Contributor Author

bors try

iohk-bors bot added a commit that referenced this pull request May 24, 2023
@iohk-bors
Copy link
Contributor

iohk-bors bot commented May 24, 2023

try

Build succeeded:

@paweljakubas paweljakubas requested a review from piotr-iohk May 24, 2023 11:26
Comment on lines 1269 to 1270
when (isNothing rewardAccountM) $
throwIO $ ExceptionReadRewardAccount ErrReadRewardAccountMissing
Copy link
Member

Choose a reason for hiding this comment

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

I wonder if we can unify the shared vs non-shared branches via:

readRewardAccount
    :: forall s. Including '[ShelleyKey, SharedKey] (KeyOf s)
    => DBLayer IO s
    -> IO (RewardAccount, XPub, NonEmpty DerivationIndex)
readRewardAccount = do
    ...
    case keyFlavor @(KeyOf s) of
        ShelleyKeyS -> ...
        SharedKeyS -> ... case ... of
            Just _ -> ...
            Nothing -> throwIO $ ExceptionReadRewardAccount ErrReadRewardAccountMissing
         

It does at least look like all callers of readSharedRewardAccount are throwing in the Nothing case anyway... Though hiding the Nothing more would be deceptive.

I suppose it would alternatively be possible to factor out the reading of the reward account somehow.

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 sugestion. done


sharedOnlyReadRewardAccount
:: forall s
. WalletFlavor s
Copy link
Member

Choose a reason for hiding this comment

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

Why not enforce that this is a shared wallet with WalletFlavor s ~ SharedWallet or something similar?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I followed the shelleyOnlyReadRewardAccount pattern here. So want unsafe version that emits error if used not with non-shared wallet.

Comment on lines +688 to +722
ErrReadRewardAccountMissing ->
apiError err501 MissingRewardAccount $ mconcat
Copy link
Member

Choose a reason for hiding this comment

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

👌 ErrConstructTxDelegationInvalid is what users would see

let (rewardAccount, derivationPath) = fromJust rewardAccountM
balance <- getCachedRewardAccountBalance netLayer rewardAccount
pp <- currentProtocolParameters netLayer
return $ case checkRewardIsWorthTxCost txWitnessTag pp era balance of
Copy link
Member

Choose a reason for hiding this comment

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

It seems checkRewardIsWorthTxCost will underestimate the cost of making a withdrawal as it doesn't take the size of the delegation script into account.

Copy link
Member

Choose a reason for hiding this comment

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

I suppose you could

A

Pass in the delegationTemplate checkRewardIsWorthTxCost. We'd then also need to update the logic here https://github.com/input-output-hk/cardano-wallet/blob/ca7eba61eb11b576d6e20a2237955c064ecd2b7a/lib/wallet/src/Cardano/Wallet/Shelley/Transaction.hs#L1774 which would be antithetical to having estimateTxSize know the bare minimum to support coin-selection.

B

Define

-- | Upper estimation of the number of bytes needed for a withdrawal.
txRewardWithdrawalSize
    :: WalletState s
    -> TxSize

which would be more in line with https://input-output.atlassian.net/browse/ADP-3016

C

Do nothing, or raise hard-code limit of 2 * costOfWithdrawal.

This would likely work fine for most users. Users with large delegation templates could lose money from withdrawals which are too small to be worth it. Although I believe it would be on the order of 0.01 ada, and at most once per epoch... So probably completely fine...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

opted for A

Copy link
Member

Choose a reason for hiding this comment

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

Unless you also update the defaultTransactionCtx in checkRewardIsWorthTxCost, your changes have no effect

https://github.com/input-output-hk/cardano-wallet/blob/f1757d4a398bc200930b316d64f82ec4e4a44a42/lib/wallet/src/Cardano/Wallet.hs#L1287-L1288

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

rewardAccountM <- readSharedRewardAccount db
when (isNothing rewardAccountM) $
throwIO $ ExceptionReadRewardAccount ErrReadRewardAccountMissing
let (rewardAccount, derivationPath) = fromJust rewardAccountM
Copy link
Member

Choose a reason for hiding this comment

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

Again no need for fromJust, they are a bad sign, and here it's completely avoidable.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

thanks to unifying readRewardAccount not valid anymore

Comment on lines +675 to +681
if ourRewardAcctM == Just rewardAcct then
constructUnsignedTx networkId (md, []) ttl wdrl
selection delta assetsToBeMinted assetsToBeBurned inpsScripts
stakingScriptM
(Write.shelleyBasedEraFromRecentEra Write.recentEra)
else
constructUnsignedTx networkId (md, []) ttl wdrl
selection delta assetsToBeMinted assetsToBeBurned inpsScripts
Nothing
(Write.shelleyBasedEraFromRecentEra Write.recentEra)
Copy link
Member

@Anviking Anviking May 25, 2023

Choose a reason for hiding this comment

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

I suspect these branches (including _ ->) and the case in mkUnsignedTx could be unified through some one

mkWithdrawal :: wallet flavor or delegationTemplate etc -> Withdrawal -> Cardano.TxWithdrawals build era

rather than having logic spread out.

Could you think about it / have look on how to reduce the complexity here? 🙏

Copy link
Member

Choose a reason for hiding this comment

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

(There seem to be so many "layers" in this module (mkUnsignedTx, mkUnsignedTransaction, constructUnsignedTransaction etc), we should move towards flattening them)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I tried to use pattern matching but in the end it turn out not to be much easier .... I agree we need to unify and cut those artificial layers - but I would write down separate ticket for that - I am happy to take it.

Copy link
Member

Choose a reason for hiding this comment

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

Thanks, please do if you see a plan of attack

@paweljakubas paweljakubas force-pushed the paweljakubas/adp-2604/withdrawals-in-multisig branch from ca7eba6 to f0561b9 Compare May 29, 2023 15:39
@paweljakubas
Copy link
Contributor Author

bors try

iohk-bors bot added a commit that referenced this pull request May 29, 2023
@iohk-bors
Copy link
Contributor

iohk-bors bot commented May 29, 2023

try

Build failed:

@paweljakubas paweljakubas requested a review from Anviking May 29, 2023 17:06
@paweljakubas
Copy link
Contributor Author

bors try

iohk-bors bot added a commit that referenced this pull request May 29, 2023
@iohk-bors
Copy link
Contributor

iohk-bors bot commented May 29, 2023

try

Build failed:

@paweljakubas paweljakubas force-pushed the paweljakubas/adp-2604/withdrawals-in-multisig branch from 9f4cfc7 to 2f5106f Compare May 30, 2023 09:23
@paweljakubas paweljakubas force-pushed the paweljakubas/adp-2604/withdrawals-in-multisig branch from 419638e to 16f0cb4 Compare May 31, 2023 10:00
@paweljakubas
Copy link
Contributor Author

bors r+

@iohk-bors
Copy link
Contributor

iohk-bors bot commented May 31, 2023

Build succeeded:

@iohk-bors iohk-bors bot merged commit 8622cfd into master May 31, 2023
@iohk-bors iohk-bors bot deleted the paweljakubas/adp-2604/withdrawals-in-multisig branch May 31, 2023 10:44
WilliamKingNoel-Bot pushed a commit that referenced this pull request May 31, 2023
…a=paweljakubas <!-- Detail in a few bullet points the work accomplished in this PR. Before you submit, don't forget to: CODE-OF-CONDUCT.md CODEOWNERS LICENSE README.md bors.toml cabal.project default.nix docker-compose.yml docs flake.lock flake.nix floskell.json hie-direnv.yaml lib nix prototypes reports scripts shell.nix 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 CODEOWNERS LICENSE README.md bors.toml cabal.project default.nix docker-compose.yml docs flake.lock flake.nix floskell.json hie-direnv.yaml lib nix prototypes reports scripts shell.nix 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 CODEOWNERS LICENSE README.md bors.toml cabal.project default.nix docker-compose.yml docs flake.lock flake.nix floskell.json hie-direnv.yaml lib nix prototypes reports scripts shell.nix 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] Added withdrawal support for multisig - [x] Added withdrawal integration test - [x] Added quit integration test - [x] Make sure getTransaction exposes certificates - shown in integration testing ### Comments <!-- Additional comments, links, or screenshots to attach, if any. --> ### Issue Number adp-2604
 <!-- 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. -->
 3970: Derive arithmetic operations for `{Coin,TokenQuantity}`. r=jonathanknowles a=jonathanknowles ## Summary
 
 This PR uses classes defined by the [`monoid-subclasses`](https://hackage.haskell.org/package/monoid-subclasses-1.2.3#readme) library to derive the definitions of all arithmetic operations for the `Coin` and `TokenQuantity` types.
 
 This takes advantage of the fact that both `Coin` and `TokenQuantity` have `Semigroup` and `Monoid` instances that are identical to those for `Sum Natural`. Co-authored-by: Pawel Jakubas <[email protected]> Co-authored-by: Piotr Stachyra <[email protected]> Co-authored-by: Jonathan Knowles <[email protected]> Source commit: 8622cfd
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