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 154 commits into
base: dev
Choose a base branch
from
Open

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

wants to merge 154 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.

Checklists for next PR

  • discuss and enhance get_public_key, get_public_key_hash, show_priv_key rpc for multi pubkey dbs

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.

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.

mm2src/coins/hd_wallet/storage/wasm_storage.rs Outdated Show resolved Hide resolved
mm2src/coins/hd_wallet/storage/wasm_storage.rs Outdated Show resolved Hide resolved
mm2src/coins/lp_coins.rs Show resolved Hide resolved
mm2src/coins/lp_coins.rs Outdated Show resolved Hide resolved
@shamardy
Copy link
Collaborator

@borngraced docker tests timeout after 90 minutes, my guess is that there is a test that uses the db that now runs forever after the current changes. can you please find the problem and try to fix it?

Copy link
Collaborator

@shamardy shamardy left a comment

Choose a reason for hiding this comment

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

Huge work! First review iteration where I cover most of the todo notes :)

Comment on lines +1583 to +1584
// TODO: db_id
let db_id: Option<String> = None;
Copy link
Collaborator

Choose a reason for hiding this comment

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

This easy to fix I think, we should use the enabled platform coin db_id. Similar to here

let db_id = coin.inner.account_db_id().unwrap_or_else(|| ctx.rmd160_hex());
let entry = active_id_chains.entry(db_id).or_insert_with(Vec::new);

I think you should start implementing account_db_id for all coins, this is needed for hd wallet (in utxo and eth) where the db_id will be the enabled_address one.

Copy link
Collaborator

Choose a reason for hiding this comment

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

c.c. @laruh

Copy link
Member

Choose a reason for hiding this comment

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

This easy to fix I think, we should use the enabled platform coin db_id

Speaking in general (not about should we use platform coin db_id or id of enabled_address): if to fix this in clear_nft_db you need to require Nft activation, then please do it. Its not a problem, since most of NFT RPC already ask about it.

I think you should start implementing account_db_id for all coins, this is needed for hd wallet (in utxo and eth) where the db_id will be the enabled_address one.

need to do a deeper review of how current multi-pubkey feature work, to answer this question.
But now my answer is we should treat global NFT the same way as erc20 token (in general implementations), it is just not registered inerc20_tokens_infos platform coin field. So nft behavior should not interfere with the implementation of suggested idea.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I think you should start implementing account_db_id for all coins, this is needed for hd wallet (in utxo and eth) where the db_id will be the enabled_address one.

This was a comment for @borngraced so no need to do a deeper review, thanks for your input :)

Copy link
Collaborator

Choose a reason for hiding this comment

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

I think you should start implementing account_db_id for all coins, this is needed for hd wallet (in utxo and eth) where the db_id will be the enabled_address one.

This is not done yet.

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/mm2_main/src/lp_swap.rs Outdated Show resolved Hide resolved
mm2src/mm2_main/src/lp_swap/pubkey_banning.rs Outdated Show resolved Hide resolved
mm2src/mm2_main/src/lp_swap/swap_v2_common.rs Outdated Show resolved Hide resolved
mm2src/mm2_main/src/lp_swap/swap_v2_common.rs Outdated Show resolved Hide resolved
Comment on lines +48 to 49
// TODO: Return public_key_hash for all available and active unique pubkeys
pub async fn get_public_key_hash(ctx: MmArc, _req: Json) -> GetPublicKeyRpcResult<GetPublicKeyHashResponse> {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same here, add this to a checklist to do in another PR. The enhancement can be to get a specific enabled coin pubkeyhash which is the enabled db_id.

mm2src/mm2_main/src/rpc/lp_commands/lp_commands.rs Outdated Show resolved Hide resolved
mm2src/mm2_main/src/lp_ordermatch.rs Outdated Show resolved Hide resolved
mm2src/mm2_main/src/lp_ordermatch.rs Outdated Show resolved Hide resolved
Comment on lines 4937 to +4938
let req: OrderStatusReq = try_s!(json::from_value(req));

let db_id: Option<String> = None; // TODO
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is tricky and not easy to solve, we need to search for a uuid across all databases. We need to check how this is used in GUIs if we want to simplify it.

@smk762
Copy link

smk762 commented May 30, 2024

For QA reference, I'll list a few things here to be tested. Please add to the list (or tell me to remove) any items which are missing/not required.

With new HD wallet:

  • Perform swap as maker / taker for UTXO, ZHTLC, tendermint, polygon. Do with parent coin and token where applicable.
  • Perform withdraw / deposit of the UTXO, ZHTLC, tendermint, polygon. Do with parent coin and token where applicable.
  • Test failed swap recovery for UTXO, ZHTLC, tendermint, polygon. Do with parent coin and token where applicable.
  • Test all NFT related functions.

DB migration tests: with old HD wallet (use master branch to generate some activity, then update to this branch):

  • Perform swap as maker / taker for UTXO, ZHTLC, tendermint, polygon. Do with parent coin and token where applicable.
  • Perform withdraw / deposit of the UTXO, ZHTLC, tendermint, polygon. Do with parent coin and token where applicable.
  • Test failed swap recovery for UTXO, ZHTLC, tendermint, polygon. Do with parent coin and token where applicable.
  • Test all NFT related functions.

Regression testing

  • With a legacy (nonHD) wallet, repeat the above tests.

Stress testing:

  • Initiate as many simultaneous swaps as possible while also initiating as many other DB triggering methods at the same time (zhtlc activation, tx history, nft update etc).

With CLI:

With Web:

  • Test the following case: 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. and its inverse.
  • Check tx history of tendermint assets to confirm tx history data is separated between inner and external accounts.

Outside the scope of testing

  • get_public_key, get_public_key_hash, show_priv_key

Related issues for context

@smk762 smk762 self-requested a review June 5, 2024 12:32
Copy link
Collaborator

@shamardy shamardy left a comment

Choose a reason for hiding this comment

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

Only 2 comments in this review iteration!

Comment on lines +1583 to +1584
// TODO: db_id
let db_id: Option<String> = None;
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think you should start implementing account_db_id for all coins, this is needed for hd wallet (in utxo and eth) where the db_id will be the enabled_address one.

This is not done yet.

coin.start_history_background_fetching(
self.ctx.metrics.clone(),
TxHistoryStorageBuilder::new(&self.ctx).build()?,
TxHistoryStorageBuilder::new(&self.ctx, coin_clone.into().account_db_id()).build()?,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Transaction history for HD wallet gets all transactions for all activated addresses, in my_tx_history_v2_impl the user specifies which address or addresses they want to see. We should used shared db for it but I see that this also create problems since activating the same address in non HD mode will lead to not knowing the shared db id. For now we can have redundancy for data where it will be fetched for both dbs, we use account_shared_db_id which should be called just shared_db_id

fn account_shared_db_id(&self) -> Option<H160> { None }

And in it's implementation we get either the shared_db_id of the hd wallet or the pubkeyhash (db_id) of other wallets depending on the activation mode.
P.S. I still need to examine this solution further to make sure it won't create any problems. Feel free to look at it also to make sure it will work fine.

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
5 participants