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

Optional change address #4129

Merged
merged 29 commits into from
Nov 22, 2023

Conversation

paweljakubas
Copy link
Contributor

@paweljakubas paweljakubas commented Sep 20, 2023

  • adjust post wallet api and enabling one change addr flag
  • extend SeqState
  • adjust nextChangeIndex
  • update db schema and related code
  • handle db migration
  • add integration test proving the case
  • allow wallet to go from multi-change-address to one-change-address mode and vice versa (update wallet api change)
  • show the case in integration testing
  • add spec
  • add PUT for shared wallets
  • do the same like for shelley for shared wallet

Comments

Issue Number

ADP-3145

@paweljakubas paweljakubas self-assigned this Sep 20, 2023
@paweljakubas paweljakubas force-pushed the paweljakubas/adp-3145/optional-change-address branch 3 times, most recently from 0312415 to a076070 Compare September 27, 2023 16:11
@paweljakubas paweljakubas marked this pull request as ready for review September 29, 2023 16:05
@paweljakubas paweljakubas force-pushed the paweljakubas/adp-3145/optional-change-address branch 3 times, most recently from 4a69010 to 9c88c24 Compare October 4, 2023 14:04
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! 😊 I have finally found the time to take a first look.

As for the user-facing design, I'm a bit unsure whether a state flag oneChangeAddressMode is the best solution — one alternative design would be to allow the user to supply an explicit change address in the "balance transaction" endpoint. That said, while this alternative has the advantage of avoiding more state, I'm not sure about it either. 🤔 In the end, I agree the state flag is reasonable.

Concerning the implementation, I have three larger requests:

  1. Instead of using Bool, could you use a more "speaking" enumeration type? I.e.
data SeqState … = { …
    , changeAddressMode :: ChangeAddressMode
    }

data ChangeAddressMode
    = SingleChangeAddress
    | IncreasingChangeAddresses

This makes the code easier to understand and maintain in the long run.

  1. For the implementation of setOneChangeAddressMode and setOneChangeAddressModeShared, we are now in the excellent position that we can work with the WalletState data type directly — it captures the entire state of the wallet in an ordinary Haskell data type, the state is no longer implicit in the database.

    I have taken care of this point and added a commit which rewrites these two functions as pure functions with a little glue code onWalletState.

  2. For the database, please use the Migration.New facilities — the old way is dead; the new way is much more robust. You will need to implement a migration and add it to runNewStyleMigrations. Implementing a new Migration is straightforward, see for example migrateDelegations in

    migration
    :: UpdateStore (SqlPersistT IO) (Operation SlotNo PoolId)
    -> ReadDBHandle IO ()
    migration store = do
    conn <- asks dbConn
    r <- liftIO $ isFieldPresent conn $ DBField StakeKeyCertSlot
    case r of
    TableMissing -> return ()
    ColumnMissing -> return ()
    ColumnPresent -> withReaderT dbBackend $ do
    old <- readOldEncoding
    writeS store old
    rawExecute "DROP TABLE stake_key_certificate" []
    rawExecute "DROP TABLE delegation_certificate" []
    migrateDelegations :: Migration (ReadDBHandle IO) 2 3
    migrateDelegations = mkMigration $ migration mkStoreDelegations

But other than that, I think this looks good.

@paweljakubas paweljakubas force-pushed the paweljakubas/adp-3145/optional-change-address branch 3 times, most recently from ff7a0be to e3481ec Compare October 13, 2023 14:44
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.

Thanks! 😊 I have a couple more requests:

  1. With the "speaking" constructors for ChangeAddressMode, the name oneChangeAddresMode no longer makes sense — changeAddresMode is better. I had change it in many places, but not all of them — could you complete this?
  2. A couple of requests on the use of the Migration.New facilities. In particular, could you move the module where the migration is define to the Checkpoints.Migration?

I'll take another look at the documentation after that.

Comment on lines 164 to 179
data ChangeAddressMode
= SingleChangeAddress
| IncreasingChangeAddresses
deriving stock (Generic, Show, Eq)
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
data ChangeAddressMode
= SingleChangeAddress
| IncreasingChangeAddresses
deriving stock (Generic, Show, Eq)
-- | How to generate change addresses.
data ChangeAddressMode
= SingleChangeAddress
-- ^ Use a single address for all change outputs.
| IncreasingChangeAddresses
-- ^ For every change output, increase a counter and derive an address from that.
deriving stock (Generic, Show, Eq)

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 339 to 342
, oneChangeAddressMode :: ChangeAddressMode
-- ^ One change address mode. If switched on then next transactions will
-- use the same change address. If no then next change index for
-- each next transaction is used
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
, oneChangeAddressMode :: ChangeAddressMode
-- ^ One change address mode. If switched on then next transactions will
-- use the same change address. If no then next change index for
-- each next transaction is used
, changeAddressMode :: ChangeAddressMode
-- ^ How to generate change addresses.

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

{ internalPool = newSeqAddressPool @n accXPub g
, externalPool = newSeqAddressPool @n accXPub g
, accountXPub = accXPub
, policyXPub = policyXPubM
, rewardAccountKey = rewardXPub
, pendingChangeIxs = emptyPendingIxs
, derivationPrefix = DerivationPrefix ( purpose, coinTypeAda, minBound )
, oneChangeAddressMode = change
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
, oneChangeAddressMode = change
, changeAddressMode = change

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 516 to 519
if oneChangeAddressMode st == SingleChangeAddress then
( ixMin, updatePending (pendingChangeIxs st) )
else
nextChangeIndex (getPool $ internalPool st) (pendingChangeIxs st)
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
if oneChangeAddressMode st == SingleChangeAddress then
( ixMin, updatePending (pendingChangeIxs st) )
else
nextChangeIndex (getPool $ internalPool st) (pendingChangeIxs st)
case changeAddressMode st of
SingleChangeAddress ->
( ixMin, updatePending (pendingChangeIxs st) )
IncreasingChangeAddresses ->
nextChangeIndex (getPool $ internalPool st) (pendingChangeIxs st)

A case statement "speaks" more, making it clearer which case is supposed to do what. 🤓

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 280 to 283
, oneChangeAddressMode :: ChangeAddressMode
-- ^ One change address mode. If switched on then next transactions will
-- use the same change address. If no then next change index for
-- each next transaction is used
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
, oneChangeAddressMode :: ChangeAddressMode
-- ^ One change address mode. If switched on then next transactions will
-- use the same change address. If no then next change index for
-- each next transaction is used
, changeAddressMode :: ChangeAddressMode
-- ^ How to generate change addresses.

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

@@ -346,6 +347,7 @@ SeqState
seqStatePolicyXPub B8.ByteString Maybe sql=policy_xpub
seqStateRewardXPub B8.ByteString sql=reward_xpub
seqStateDerivationPrefix W.DerivationPrefix sql=derivation_prefix
seqStateOneChangeAddrMode W.ChangeAddressMode sql=change_addr_mode
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
seqStateOneChangeAddrMode W.ChangeAddressMode sql=change_addr_mode
seqStateChangeAddrMode W.ChangeAddressMode sql=change_addr_mode

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

@@ -433,6 +435,7 @@ SharedState
sharedStateDelegationScript (Script Cosigner) Maybe sql=delegation_script
sharedStateRewardAccount W.RewardAccount Maybe sql=reward_account
sharedStateDerivationPrefix W.DerivationPrefix sql=derivation_prefix
sharedStateOneChangeAddrMode W.ChangeAddressMode sql=change_addr_mode
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
sharedStateOneChangeAddrMode W.ChangeAddressMode sql=change_addr_mode
sharedStateChangeAddrMode W.ChangeAddressMode sql=change_addr_mode

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 783 to 792
-- | Adds an 'one_change_addr_mode' column to the 'seq_state'
-- table if it is missing.
--
addOneChangeAddrModeIfMissing :: Sqlite.Connection -> IO ()
addOneChangeAddrModeIfMissing conn = do
addColumn_ conn True (DBField SeqStateOneChangeAddrMode) value
where
value = "FALSE"

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
-- | Adds an 'one_change_addr_mode' column to the 'seq_state'
-- table if it is missing.
--
addOneChangeAddrModeIfMissing :: Sqlite.Connection -> IO ()
addOneChangeAddrModeIfMissing conn = do
addColumn_ conn True (DBField SeqStateOneChangeAddrMode) value
where
value = "FALSE"

This goes away now.

@@ -170,6 +170,7 @@ migrateManually tr key defaultFieldValues =
, moveRndUnusedAddresses
, cleanupSeqStateTable
, addPolicyXPubIfMissing
, addOneChangeAddrModeIfMissing
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
, addOneChangeAddrModeIfMissing

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

Copy link
Contributor

Choose a reason for hiding this comment

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

Could you please move this module to Cardano.Wallet.DB.Store.Checkpoints.Migration? That puts it closer to the thing that is being migrated (i.e. the address state).

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 paweljakubas force-pushed the paweljakubas/adp-3145/optional-change-address branch 3 times, most recently from 127105d to 42de1ff Compare October 19, 2023 15:46
@paweljakubas paweljakubas force-pushed the paweljakubas/adp-3145/optional-change-address branch from 42de1ff to 2229d7d Compare October 20, 2023 14:56
@paweljakubas paweljakubas force-pushed the paweljakubas/adp-3145/optional-change-address branch from fd8163f to 3db4946 Compare October 30, 2023 08:35
@HeinrichApfelmus HeinrichApfelmus force-pushed the paweljakubas/adp-3145/optional-change-address branch 8 times, most recently from 05e5e67 to 0937343 Compare November 17, 2023 11:58
@paweljakubas paweljakubas force-pushed the paweljakubas/adp-3145/optional-change-address branch from f161566 to 288700e Compare November 22, 2023 09:13
@paweljakubas paweljakubas added this pull request to the merge queue Nov 22, 2023
Merged via the queue into master with commit e5a6ca6 Nov 22, 2023
2 checks passed
@paweljakubas paweljakubas deleted the paweljakubas/adp-3145/optional-change-address branch November 22, 2023 10:28
WilliamKingNoel-Bot pushed a commit that referenced this pull request Nov 22, 2023
…nts the 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 default.nix docker-compose.yml docs flake.lock flake.nix floskell.json fourmolu.yaml hie-direnv.yaml justfile 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 CONTRIBUTING.md LICENSE MAINTAINERS.md README.md cabal.project default.nix docker-compose.yml docs flake.lock flake.nix floskell.json fourmolu.yaml hie-direnv.yaml justfile 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 CONTRIBUTING.md LICENSE MAINTAINERS.md README.md cabal.project default.nix docker-compose.yml docs flake.lock flake.nix floskell.json fourmolu.yaml hie-direnv.yaml justfile 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] adjust post wallet api and enabling one change addr flag - [x] extend SeqState - [x] adjust nextChangeIndex - [x] update db schema and related code - [x] handle db migration - [x] add integration test proving the case - [x] allow wallet to go from multi-change-address to one-change-address mode and vice versa (update wallet api change) - [x] show the case in integration testing - [x] add spec - [x] add PUT for shared wallets - [x] do the same like for shelley for shared wallet ### Comments <!-- Additional comments, links, or screenshots to attach, if any. --> ### Issue Number ADP-3145 Source commit: e5a6ca6
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