-
Notifications
You must be signed in to change notification settings - Fork 94
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
[feature request] HD Wallet (multi-account) #740
Comments
@ca333 Thanks for creating the issue, it will be nice enhancement indeed! |
By implementing PR for offline staking of QTUM I realized the need for this feature. In general, offline staking does not mix well with active trading. My idea to go to multi-address without having to refactor everything and break everything would rather be to make this feature work only on the new compatible bip39 / bip44 seed and by definition to have the bip39 address + the derived bip44 address. I imagine an option when starting AtomicDEX to no longer use the Iguana derivation, but bip39 and from there add an optional address collection next to our main address. After that, we could refactor the functions one by one to automatically fall back to the primary address in case. So #[allow(dead_code)]
#[derive(Deserialize)]
pub struct WithdrawRequest {
coin: String,
to: String,
#[serde(default)]
amount: BigDecimal,
#[serde(default)]
max: bool,
fee: Option<WithdrawFee>,
// If not None used as from address instead of the default one
from: Option<String>
} and an RPC In the same idea, later my_balance will be able to return the balance of all the addresses, but by default keep the same behaviour. And we can abuse the V2 of the RPC for this kind of operation. Otherwise, we can also introduce RPC like |
I like the idea of having the |
* Refactor `init_utxo` according to a unified `init_standalone_coin` protocol * Move `PrivKeyBuildPolicy` to `lp_coins.rs` * Refactor `grpc_web_multi_url_request` * Add `MmRpcResult::map_err`, `RpcTaskStatus::map_err` * Push missing files * Initialize UTXO coin with a pubkey requested from a Trezor device * Move `UtxoCoinBuilder`, `UtxoArcBuilder` from `utxo.rs` to a separate module * Add `extended_pubkey`, `derivation_path` to `HDWalletInfo` * Implement requesting balances of HD wallet addresses * Move `extended_pubkey` from `UtxoHDWallet` to `UtxoHDAccount` * Register `UtxoStandardCoin` at `InitStandaloneCoinActivationOps::init_standalone_coin` * Add `RpcDerivationPath` * Push missed `coin_balance.rs` * Increase `WAIT_DOCKER_READY_TIMEOUT_MS` to 60s * Bump the `ring` crate version to 0.16.15 * Add `wallet_balance` RPC call * Fix zhtlc feature compilation errors * Add ZCoinBuilder * Minor changes * Optimize UTXO coin builders not to clone `UtxoActivationParams` * Refactor `NativeClient::list_transactions_by_address` to `NativeClient::is_address_list_transactions_empty` * Fix WASM, ZCash compile errors * Fix rustfmt warnings * Fix compilation of docker tests * Add QTUM coin initialization with Trezor * Add `init_qtum`, `init_qtum_status`, `init_qtum_user_action` RPC calls * Add `derivation_path` to `HDAccountBalance` * Fix `recreate_swap_data::convert_maker_to_taker_events` * Return the previous implementation of `grpc_web_multi_url_request` * Split `wallet_balance` into `hd_account_balance` and `check_hd_account_balance` RPC calls * Add check_utxo_maturity to electrum/enable RPC call (#1201) * Add `check_utxo_maturity` to electrum/enable RPC call * Add `QtumCoinBuilder` and `QtumCoinWithIguanaPrivKeyBuilder` that override `check_utxo_maturity` * Add `UtxoCommonOps::list_all_unspent_ordered` that behaves as `UtxoCommonOps::list_unspent_ordered` before * `UtxoCommonOps::list_unspent_ordered` checks the `check_utxo_maturity` flag to use either `list_all_unspent_ordered` or `list_mature_unspent_ordered` * Rename `UtxoCommonOps::ordered_mature_unspents` to `UtxoCommonOps::list_mature_unspent_ordered` * Add `get_new_hd_address`, `init_create_new_hd_account` RPC calls * Use `tokio::RwLock` instead of `parking_lot::Mutex` to store HD accounts * Move HD wallet related traits and structures from lp_coins.rs to coin_hd_wallet.rs * TODO use `HwRpcTaskAwaitingStatus`, `HwRpcTaskUserAction`, `HwRpcTaskUserActionRequest`, `InitRpcTaskResponse`, `RpcTaskActionError`, `RpcTaskStatusError`, `RpcTaskStatusRequest` everywhere it's possible * Use RPC common structures and errors wherever possible * Use `futures::lock::Mutex` instead of `tokio::lock::RwLock` * Fix utxo_tests compile errors * Perform naming refactoring * Add the `HDWalletCoinAndBalanceOps` trait alias * Add `HDWalletOps` and `HDAccountOps` * Move the `HDWallet` related methods from `HDWalletCoinOps` into `HDWalletOps` * Move the `HDAccount` related methods from `HDWalletCoinOps` into `HDAccountOps` * Rename `get_new_hd_address` to `get_new_address`, `hd_account_balance` to `account_balance`, `init_create_hd_account` to `init_create_account` RPC calls * Refactor `XPubExtractorUnchecked` * Refactor generic type bounds (#1211) * Possible refactoring. * Removed more bounds. * Added HDAccount for HDWalletCoinOps to reduce "as HDWalletOps" constructions. * Continue refactoring * Add a default implementation of `HDWalletCoinOps::generate_new_address` * Remove `HDWalletCoinOps::address_balance` * Make `HDWalletBalanceRpcOps` independent of `HDWalletBalanceOps` Co-authored-by: Artem Vitae <artem@vitae.com> * Check if the specified `WithdrawRequest::from` DerivationPath/AccountId refers to an activated account/address * Add the `WithdrawFrom::AccountId` variant to allow the user to specify account_id, chain and address_id * Add `Bip44DerivationPath`, `Bip44PathToCoin`, `Bip44PathToAccount` * Avoid extracting a pubkey from a Trezor device on `init_withdraw` * Fix PR issues * Avoid using `clippy::type_complexity` by refactoring the `RpcTask` module * Typo: address_unspendable_balanAce * Fix PR issues, make `RpcTaskId` unique * Rename `ExpectedHDWalletDerivationMethod` to `CoinIsActivatedNotWithHDWallet` * Reorder RPCs alphabetically * impl `From<KeyPair>` * Fix rustfmt * Remove `KeyPairArc::from_key_pair` Co-authored-by: Artem Vitae <artem@vitae.com>
* Add `HDWalletCoinWithStorageOps`, `HDWalletCoinStorage` * Add `HDAccountStorageItem` IndexedDb table * Add and implement `HDWalletIndexedDbStorage`, `HDWalletDb` in WASM * Integrate HD wallet storage to mm2 * Load HD accounts on coin initialization * Updating number of known addresses on `get_new_address`, `scan_for_new_addresses` RPC calls * Clearing DB if an error occurs on loading HD accounts * Don't extract xpub on coin initialization, extract it on `get_activation_result` if necessary * Remove `UtxoArcWithIguanaPrivKeyBuilder` * Implement HD wallet sqlite storage * Replace `wallet_id` column with `coin`, `mm2_rmd160` and `hd_wallet_rmd160` within the storage * Add `HDWalletMockStorage` for testing purposes * Minor refactoring * Rename `AddressChecker` to `AddressScanner` * Refactor `DerivationMethodNotSupported` * Rename `DerivationMethodNotSupported` error to `UnexpectedDerivationMethod` * Minor changes * Temporary disable the `polygon_check_if_my_payment_sent` test * Don't allow using `HDWalletMockStorage` in WASM * Make `HDWalletSqliteStorage::update_addresses_number` safe * Make `CreateNewAccountParams::scan` boolean * Minor fixes * PR fixes
#964 #740 * Restructure TX history storage modules * Add `coins::tx_history_storage` module * Move `load_history`, `save_history`, `clear` from `TxHistoryDb` implementation to static functions * Add `BeBigUint` into `common::indexed_db` * Cover `BeBigUint` with unit tests * Add `IndexedDbTxHistoryStorage` * Add `indexed_db::DbTable::count`, `indexed_db::DbTable::count_all` * Add methods to `indexed_db::DbTable` that take multiple index keys as arguments * Remove `DbTransaction::wait_for_complete` as it doesn't work properly * Integrate HD addresses into TxHistory V2 Storage scheme * Add tx history `WalletId` * Add `SqlQuery` that acts like `SqlBuilder` but manages parameters * Add `<WalletId>_tx_from_address`, `<WalletId>_tx_to_address` SQL tables * Minor changes * Add `try_serialize_index_value` macro * Avoid declaring public methods, traits, types * Fix PR issues * Move big JSON payloads to separate files * Add the `indexed_db::test_transaction_abort_on_error` test * Allow the `SqlQuery` to validate SQL identifiers and values * Combine `tx_from_address` and `tx_to_address` tables into single `tx_address` * Fix clippy warning * Fix PR issues * Avoid adding `mm2src/coins/for_tests/RICK_<ID>.json` files * Minor changes
#964 #740 * Restructure TX history storage modules * Add `coins::tx_history_storage` module * Move `load_history`, `save_history`, `clear` from `TxHistoryDb` implementation to static functions * Add `BeBigUint` into `common::indexed_db` * Cover `BeBigUint` with unit tests * Add `IndexedDbTxHistoryStorage` * Add `indexed_db::DbTable::count`, `indexed_db::DbTable::count_all` * Add methods to `indexed_db::DbTable` that take multiple index keys as arguments * Remove `DbTransaction::wait_for_complete` as it doesn't work properly * Integrate HD addresses into TxHistory V2 Storage scheme * Add tx history `WalletId` * Add `SqlQuery` that acts like `SqlBuilder` but manages parameters * Add `<WalletId>_tx_from_address`, `<WalletId>_tx_to_address` SQL tables * Minor changes * Add `try_serialize_index_value` macro * Avoid declaring public methods, traits, types * Fix PR issues * Move big JSON payloads to separate files * Add the `indexed_db::test_transaction_abort_on_error` test * Allow the `SqlQuery` to validate SQL identifiers and values * Combine `tx_from_address` and `tx_to_address` tables into single `tx_address` * Fix clippy warning * Fix PR issues * Avoid adding `mm2src/coins/for_tests/RICK_<ID>.json` files * Minor changes
* Add `gui-storage` feature * Add `gui_storage::account::AccountStorage` trait, implement it in WASM * Add `gui_storage::enable_account`, `gui_storage::add_account`, `gui_storage::get_accounts`, `gui_storage::set_account_name`, `gui_storage::set_account_description`, `gui_storage::activate_coint`, `gui_storage::deactivate_coint` RPCs * WIP start implementing `SqliteAccountStorage` * Add `common::fmt` formatting utils * Add `db_common::sql_create::SqlCreate` builder * Push missing files * Fix compile errors after merging `dev` * Start implementing `SqliteAccountStorage` * Implement `SqliteAccountStorage::load_accounts_with_enabled_flag` * Continue implementing `SqliteAccountStorage` * Implement `SqliteAccountStorage::[load_enabled_account_id, load_enabled_account_with_coins]` methods * Add `SqlInsert` * Refactor quoted params in `SqlQuery`, `SqlCreate` * Add optional parameters to `SqlQuery`, `SqlCreate`, `SqlInsert` * Add `EnabledAccountId` to avoid enabling HW account * Use `device_pubkey` as an identifier of `AccountId::HW` * Remove `gui-storage` feature, add a few tests * Fix `SqlQuery::and_where_eq_param` and `SqlQuery::or_where_eq_param` if param is `OwnedSqlParam::Null` * Fix invalid index error in WASM * Implement `enable_account` for the SQL storage * Add `test_enable_account_impl` * Add WIP `SqlDelete` request builder * Refactor old and add new SQL builders * Add `SqlCondition`, move `where` impls from `SqlQuery` to `SqlCondition` * Implement `AccountStorage::set_name` for `SqliteAccountStorage` * Add `test_set_name` tests * Continue implementing `AccountStorage` for `SqliteAccountStorage` Implement `AccountStorage::[set_description, set_balance]` for `SqliteAccountStorage` * Finish implementing `AccountStorage` for `SqliteAccountStorage` * Implement `AccountStorage::[activate_coins, deactivate_coins]` for `SqliteAccountStorage` * Add `test_activate_deactivate_coins` test * Fix clippy warnings, add one more test * Add `gui_storage::delete_account` RPC * Add `mm2_tests::test_gui_storage` integration test * Fix udeps * Fix PR issues * Rename `lock_db` and `lock_conn` to `lock_db_mutex` and `lock_conn_mutex` respectively * Add `PrimaryKey` and `ForeignKey` SQL constraints * Add "pragma foreign_keys = ON;" on * Fix `Unique` constraint by making the constraint name required * Get rid of unnecessary checks by using PRIMARY and FOREIGN keys * * Add PRIMARY KEY for `account_table` * Add FOREIGN KEY for `account_coins_table` * Add `device_pubkey` into `enabled_account_table` to declare FOREIGN KEY * Add `foreign_columns` macro * Replace all `WASM::AccountTable` indexes with `ACCOUNT_ID_INDEX` * Refactor FOREIGN KEY helpers * Add missing and new RPCs * Add missing `get_enabled_account_with_coins` RPC * Add new `get_account_coins` RPC * Fix fmt warning * Fix `mm2_tests::test_gui_storage` (probably still panics) * Make `mm2_tests::test_gui_storage` green again * Fix PR issues * Validate the requests before getting an `AccountContext` * Split `mm2_tests::test_gui_storage` into `test_gui_storage_accounts_functionality` and `test_gui_storage_coins_functionality`. * Cover all `gui_storage` RPCs in `mm2_tests` * Fix PR issues Rename the `gui_storage` crate into `mm2_gui_storage` * Minor changes * Minor changes
* Add `HdAccountCtx` to `CryptoCtx` as an alternative to `IguanaCtx` * Rename `CryptoCtx::secp256k1_pubkey*` to `CryptoCtx::mm2_internal_pubkey*` * Remove `MmCtx::secp256k1_key_pair()` * TODO: remove `MmCtx::secp256k1_key_pair_as_option()` and ``MmCtx::secp256k1_key_pair` * Fix some TODOs * Add `PrivKeyBuildPolicy::GlobalHDAccount` * Add `Secp256k1Secret` and `IguanaPrivKey` aliases, use it everywhere instead of the `[u8]` slice * Remove `MmCtx::secp256k1_key_pair` * Add common `InternalError` * Add `DiscardMmResult`, `SplitMmResult` traits to `mm2_error_handle` * Move `MmCtx::public_id()` to `CryptoCtx::mm2_internal_public_id()` * Remove unused dependencies * Implement `CryptoCtx::init_with_global_hd_account` * Add `hd_account_id` conf param * Cover swaps in tests * Fix TODOs * Rename `DerivationMethod::Iguana` to `DerivationMethod::SingleAddress` * Rename `PrivKeyNotAllowed` to `PrivKeyPolicyNotAllowed` * Cover `hd_account_id` with tests * * Fix fmt warnings * Fix wasm tests * Fix RICK-MORTY swap * Use `NegotiationDataMsg::V3` even if maker and taker pubkeys are the same but differ from persistent pub * Log Swap error event in WASM * Fix TODOs * Minor changes * Remove `PrivKeyBuildPolicy::GlobalHDAccount` * Rename `PrivKeyBuildPolicy::IguanaPrivKey` to `Secp256k1Secret` * Fix PR issues * Fix `CryptoCtx` comments * Simplify `if` conditions for Negotiation message * Use `is_my_order` within `request_and_fill_orderbook` * Remove `IguanaCtx`, move `secp256k1_key_pair` to `CryptoCtx` * Remove unnecessary methods from `GlobalHDAccountCtx` * Rename `CryptoCtx::mm2_internal_privkey_bytes` to `mm2_internal_privkey_secret` * Distinguish the common implementation of `CryptoCtx` initializers * Remove `mm2_internal_key_pair` from `GlobalHDAccountCtx` * Return PrivKeyBuildPolicy::GlobalHDAccount * Fix ZCoin BIP32 derivation * Allo the user to specify `32`, `44`, `49`, `84` purposes in `derivation_path` * Rename `Bip44DerivationPath` to `StandardHDPath` * Add `z_derivation_path` to `ZCoinProtocolInfo` * Check if `BTC-segwit` derivation works * Minor fix * Rename `DiscardMmResult::discard_mm` to `DiscardMmTrace::discard_mm_trace` * Ignore Tendermint tests * Fix `test_withdraw_segwit`
@sergeyboyko0791 Could you please post a comprehensive test plan on testing the global HD feature? It should contain reference wallets to check against, etc. |
Global HD account feature allows the user to use the BIP32/BIP44/BIP49/BIP84 derivation scheme at the following path: For example, if the user wants to activate a 3rd HD account ( {
"gui": "DEVDOCS_CLI",
"netid": 7777,
"rpc_password": "YOUR_PASS_HERE",
"passphrase": "BIP39 MNEMONIC PHRASE",
// ...
"hd_account_id": 3
} Please note that if Coin activationIn order to activate coins, they have to contain {
"coin": "BTC",
"name": "bitcoin",
// ...
"derivation_path": "m/44'/0'"
} Testing plan
{
"coin": "ZOMBIE",
"asset": "ZOMBIE",
"txversion": 4,
"overwintered": 1,
"mm2": 1,
"protocol": {
"type": "ZHTLC",
"protocol_data": {
"consensus_params": {
"overwinter_activation_height": 0,
"sapling_activation_height": 1,
"blossom_activation_height": null,
"heartwood_activation_height": null,
"canopy_activation_height": null,
"coin_type": 133,
"hrp_sapling_extended_spending_key": "secret-extended-key-main",
"hrp_sapling_extended_full_viewing_key": "zxviews",
"hrp_sapling_payment_address": "zs",
"b58_pubkey_address_prefix": [28, 184],
"b58_script_address_prefix": [28, 189]
},
"check_point_block": {
"height": 290000,
"time": 1664200629,
"hash": "106BAA72C53E7FA52E30E6D3D15B37001207E3CF3B9FCE9BAB6C6D4AF9ED9200",
"sapling_tree": "017797D05B070D29A47EFEBE3FAD3F29345D31BE608C46A5131CD55D201A631C13000D000119CE6220D0CB0F82AD6466B677828A0B4C2983662DAB181A86F913F7E9FB9C28000139C4399E4CA741CBABBDDAEB6DCC3541BA902343E394160EEECCDF20C289BA65011823D28B592E9612A6C3CF4778F174E10B1B714B4FF85E6E58EE19DD4A0D5734016FA4682B0007E61B63A0442B85E0B8C0CE2409E665F219013B5E24E385F6066B00000001A325043E11CD6A431A0BD99141C4C6E9632A156185EB9B0DBEF665EEC803DD6F00000103C11FCCC90C2EC1A126635F708311EDEF9B93D3E752E053D3AA9EFA0AF9D526"
},
"z_derivation_path": "m/32'/133'",
}
},
"required_confirmations": 0,
"derivation_path": "m/44'/133'",
} Please note: cc: @smk762 @tonymorony |
Please note that lightning derivation path is still an open for research topic after I discussed it with @sergeyboyko0791 on DM. Different lightning node implementations use different derivation paths, e.g.:
In addition to how the master lightning node keys are generated, channel backups are not compatible between different node implementations as well.
Currently in AtomicDEX lightning implementation the node's master key is generated from the platform's private key, a bit similar to how it's done in Core Lightning but only one child level is used to get the node's secret that generates the node's publickey/address. Different hardened childs are used to generate more master keys that are important for the node's operation. |
Testing completed prior to merge, though there have since been changes to z_coin code so will recheck that this week |
Multi Account wallet BIP44 integration alongside BIP39 will be nice enhancement - GUI developers and CLI users would not worry about key-management anymore. Furthermore we can extend this beyond wallet into the DEX - will increase user/dev experience. I envision it one day user can chose which "account" (derivation path/key) to use for specific atomic trades or wallet operations. And as positive effect users can reuse mnemonic from other BIP32/39/44 wallets.
resources:
https://www.reddit.com/r/Bitcoin/comments/2srxr2/what_is_the_difference_between_bip_32_and_bip_44/cnspxwq/
rust lib: https://github.com/rust-bitcoin/rust-wallet (not secure code reviewed)
The text was updated successfully, but these errors were encountered: