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

feat(core): multi-pubkey DB support #2093

Open
wants to merge 142 commits into
base: dev
Choose a base branch
from
Open

feat(core): multi-pubkey DB support #2093

wants to merge 142 commits into from

Conversation

onur-ozkan
Copy link
Member

@onur-ozkan onur-ozkan commented Apr 1, 2024

This pull request enables support for managing multiple public keys in mm2 databases. Initially, a single database instance is generated using the startup public key rmd160. With this update, the mm_ctx will manage multiple database instances by leveraging the public key from MmCoin::account_db_id if defined, or defaulting to the mm2 startup public key.

Completed

  • Introduced sql_connection_pool for managing all instances of shared and sqlite connections from one place
  • Introduced async_sql_connection_pool for managing all instances of async sqlite connections from one place
  • Refactored indexeddb driver implementation to allow multi pubkey support
  • Refactored SwapContext, MySwapStorage, MakerSwapStorage, TakerSwapStorage NftCtx, UtxoBlockHeaderStorage, Zcoin storages(web only), lp_ordermatch and other storage impl to support multipubkey
  • Implement database migrations upon new database instance creation or account activation using a custom public key.

Complex Todos:

  • kick_start unfinished swap upon new database instance creation or account activation using a custom public key.

Todos

  • Further refactor some RPC methods to enable results for a single public key or all active public keys.

Signed-off-by: onur-ozkan <work@onurozkan.dev>
Signed-off-by: onur-ozkan <work@onurozkan.dev>
Signed-off-by: onur-ozkan <work@onurozkan.dev>
@onur-ozkan onur-ozkan added enhancement New feature or request in progress Changes will be made from the author labels Apr 1, 2024
@borngraced borngraced self-assigned this Apr 9, 2024
@borngraced borngraced marked this pull request as ready for review April 10, 2024 20:01
Copy link
Member Author

@onur-ozkan onur-ozkan 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 for the work @borngraced. We need to add test coverage on this massive change of core mm2 logic.

This PR needs to be tested very carefully.

cc @KomodoPlatform/qa

Some initial notes from my end:

@@ -219,25 +220,27 @@ impl Default for HDWalletCoinStorage {
}

impl HDWalletCoinStorage {
// TODO: Since hd_wallet_rmd160 is unique for a device, do we use it as db_id too? or we can just use mm2 shared_db_id and use hd_wallet_rmd160 for primary key as it's currently done
Copy link
Member Author

Choose a reason for hiding this comment

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

Can we combine hd wallet with external wallets? I don't think it is possible, is it? @shamardy

Copy link
Collaborator

@shamardy shamardy May 20, 2024

Choose a reason for hiding this comment

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

I've previously discussed this with @borngraced via DM. The db path which stores accounts and addresses previously utilized by the user (which is hd_wallet_rmd160) should be global for a seed. However, each address should use its own db path for orders, swaps, etc.

This approach ensures more flexibility. For instance, if the same seed is used in both Keplr and mm2, and a swap is initiated using Keplr, then the app was closed midway through the swap. Upon restarting, if the Tendermint coin is activated using mm2 seed and the address enabled for swaps is the same address that was used before in Keplr, the swap will complete successfully.

Copy link
Collaborator

@shamardy shamardy May 20, 2024

Choose a reason for hiding this comment

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

For instance, if the same seed is used in both Keplr and mm2, and a swap is initiated using Keplr, then the app was closed midway through the swap. Upon restarting, if the Tendermint coin is activated using mm2 seed and the address enabled for swaps is the same address that was used before in Keplr, the swap will complete successfully.

I guess this is one of the test cases that should be tested by QA/GUI team once this PR is ready for testing
c.c. @smk762 @naezith

mm2src/coins/hd_wallet/storage/mod.rs Outdated Show resolved Hide resolved
mm2src/coins/lightning/ln_utils.rs Outdated Show resolved Hide resolved
mm2src/coins/lp_coins.rs Outdated Show resolved Hide resolved
mm2src/mm2_db/src/indexed_db/db_lock.rs Outdated Show resolved Hide resolved
Comment on lines 174 to 176
pub async fn enable_account(ctx: MmArc, req: EnableAccountRequest) -> MmResult<SuccessResponse, AccountRpcError> {
let account_ctx = AccountContext::from_ctx(&ctx).map_to_mm(AccountRpcError::Internal)?;
// TODO db_id
let account_ctx = AccountContext::from_ctx(&ctx, None).map_to_mm(AccountRpcError::Internal)?;
Copy link
Member Author

Choose a reason for hiding this comment

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

I guess there is no way for this function to figure out db_id, if I am not mistaken? If I am right, we should probably extend the function args with db_id arg.

Copy link
Member

Choose a reason for hiding this comment

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

Yeah there're some other rpc methods like this too.. cc @shamardy

Copy link
Collaborator

@shamardy shamardy May 20, 2024

Choose a reason for hiding this comment

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

This is part of the GUI storage methods which was done by Sergey a long time ago and we later decided to not utilize it for HD wallet. GUI storage methods can be safely removed from the codebase, if we ever need it in the future, we can get it from commits history but my implementation approach for HD wallets will not need it as far as I can see.

Copy link
Member Author

Choose a reason for hiding this comment

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

I guess just comment them out?

@onur-ozkan
Copy link
Member Author

onur-ozkan commented May 14, 2024

Complex Todos:

  • Implement database migrations upon new database instance creation or account activation using a custom public key.
  • kick_start unfinished swap upon new database instance creation or account activation using a custom public key.

Currently, without making a big refactoring, this can be achieved from the coin activation functions I believe.

@borngraced
Copy link
Member

borngraced commented May 16, 2024

Complex Todos:

  • Implement database migrations upon new database instance creation or account activation using a custom public key.
  • kick_start unfinished swap upon new database instance creation or account activation using a custom public key.

Currently, without making a big refactoring, this can be achieved from the coin activation functions I believe.

yep I accomplished task 1 by implementing a db migration watcher which keeps track of new db_id and run migrations/fix shared_db_dir if needed b370bec

Copy link
Member Author

@onur-ozkan onur-ozkan left a comment

Choose a reason for hiding this comment

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

yep I accomplished task 1 by implementing a db migration watcher which keeps track of new db_id and run migrations/fix shared_db_dir if needed b370bec

Q: What we call first when we are about to create new db? Can we do this migrations in the on-demand mode without running async runtime?

mm2src/coins/eth.rs Outdated Show resolved Hide resolved
mm2src/coins/lp_coins.rs Outdated Show resolved Hide resolved
mm2src/coins/nft/nft_structs.rs Outdated Show resolved Hide resolved
Copy link
Member Author

@onur-ozkan onur-ozkan left a comment

Choose a reason for hiding this comment

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

Can you add a TODO note somewhere on db id handling implementation which includes the address of #2122 issue ?

mm2src/mm2_core/src/sql_connection_pool.rs Outdated Show resolved Hide resolved
mm2src/mm2_core/src/sql_connection_pool.rs Outdated Show resolved Hide resolved
Copy link
Member Author

@onur-ozkan onur-ozkan left a comment

Choose a reason for hiding this comment

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

I think tendermint_tx_history_v2 also needs some magic in order to keep the history data separated between inner-external accounts 🫤 I hope I am wrong.. A confirmation from GUI team or QA team could be nice.

Ok(HDWalletIndexedDbStorage { db })
Ok(HDWalletIndexedDbStorage {
db,
db_id: db_id.map(|e| e.to_string()),
Copy link
Member Author

Choose a reason for hiding this comment

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

e may lead to confusions as it refers to error in most cases.

Suggested change
db_id: db_id.map(|e| e.to_string()),
db_id: db_id.map(|str| str.to_string()),

OR:

Suggested change
db_id: db_id.map(|e| e.to_string()),
db_id: db_id.map(String::from),

Copy link
Member

Choose a reason for hiding this comment

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

done

Comment on lines 322 to 325
/// This function is used in `hd_wallet_storage::tests`.
pub(super) async fn get_all_storage_items(ctx: &MmArc) -> Vec<HDAccountStorageItem> {
let coins_ctx = CoinsContext::from_ctx(ctx).unwrap();
let db = coins_ctx.hd_wallet_db.get_or_initialize().await.unwrap();
let db = coins_ctx.hd_wallet_db.get_or_initialize(None).await.unwrap();
Copy link
Member Author

Choose a reason for hiding this comment

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

Can we add conditional compilation attributes on fn get_all_storage_items to make it accessible only from tests?

Copy link
Member

Choose a reason for hiding this comment

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

done

mm2src/coins/lp_coins.rs Show resolved Hide resolved
Comment on lines 4592 to 4600
if active_only && coin.is_available() {
account_ids.insert(account.clone());
continue;
};

if !active_only {
account_ids.insert(account);
continue;
}
Copy link
Member Author

Choose a reason for hiding this comment

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

nit: active_only && coin.is_available() || !active_only should handle both in single block.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request in progress Changes will be made from the author
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Implementing Per-Coin Database Paths Based on PubkeyHash for Enhanced Modularization
3 participants